Импорт стандартных модулей. Команды import и from

Курс по Python: https://stepik.org/course/100707

Этим занятием мы открываем новую тему, связанную с модулями и пакетами. В некоторых программах этого курса я уже делал импорт стандартных модулей, например:

import math
import time

чтобы использовать их функции. Но что они из себя представляют? В действительности, модуль – это обычный текстовый файл программы на языке Python. В этом легко убедиться, если в PyCharm нажать и удерживать клавишу Ctrl и щелкнуть по имени модуля, например, math. Откроется файл и мы можем ознакомиться с его содержимым.

Второй вопрос, а что собственно делает конструкция import? Как он импортирует этот текст программы в нашу программу? Давайте я с помощью функции locals() выведу все локальные переменные нашей программы:

print(locals())

В консоли у нас появился словарь и последними записями в нем идут имена math и time, которые ссылаются на соответствующие импортированные модули. Для более читаемого вида этой информации я импортирую еще один модуль:

import pprint

и из него вызову функцию с тем же именем:

pprint.pprint(locals())

Теперь мы видим все гораздо нагляднее. Кстати, дополнительно появилась еще одна строчка с именем pprint после его импортирования. Так вот, все эти имена: math, pprint, time – это переменные в нашей программе и каждая ссылается на свое пространство имен, со своими глобальными переменными. Например, чтобы посмотреть, что содержит модуль math, можно получить все ее переменные с помощью функции dir:

pprint.pprint(dir(math))

Мы видим полный список глобальных атрибутов этого модуля, включая имена функций и переменных. То есть, чтобы обратиться к определенной функции в своей программе, нам нужно написать имя импортируемого модуля и через точку указать имя функции или переменной, например:

a = math.ceil(1.8)
print(a)
print(math.pi)

То есть, в сточке import math автоматически создается пространство имен math в нашей программе, через которое мы можем обращаться к любому глобальному атрибуту этого модуля. И так с каждым импортируемым модулем.

Все эти модули, что я использовал, поставляются вместе с языком Python и составляют его стандартную библиотеку. Что еще входит в нее? Полный список модулей и подробное их описание приведено на странице официальной документации:

https://docs.python.org/3/library/

Я рекомендую вам в целом с ней ознакомиться, чтобы представлять ее возможности и использовать в своей программе готовый функционал, а не изобретать собственные велосипеды.

Далее, предположим, что мы в своей программе используем переменную с именем:

math = 'математика'

В итоге, в нашей программе, сначала при импорте math будет создана глобальная переменная math на импортируемый модуль, а затем, эта переменная станет ссылаться на строку. В результате мы уже не можем воспользоваться модулем math в своей программе и попытки обратиться к функции или переменной приведут к ошибкам.

Как разрешить эту ситуацию? Язык Python позволяет нам в момент импорта указывать псевдонимы импортируемых модулей, используя ключевое слово as, например:

import math as mt

И, далее, по программе использовать переменную mt в качестве имени модуля. На практике такая подстановка выполняется в двух целях. Во-первых, чтобы избежать возможного конфликта имен в программе и, во-вторых, для удобства, если имя модуля слишком длинное, то имеет смысл записать его более короткий псевдоним.

Когда импортируется модуль через import, то автоматически подключается все его пространство имен к нашей программе. Однако, часто из всего этого многообразия используется всего несколько функций или переменных. И, если мы не хотим подключать модуль целиком, а сделать выборочный импорт некоторых его атрибутов, то для этого следует использовать другую конструкцию:

from math import ceil, pi

Смотрите, теперь, при выводе:

pprint.pprint(locals())

мы не видим имя модуля math, но в пространстве имен нашей программы появляются имена ceil и pi. То есть, для их использования мы теперь должны обращаться к ним напрямую:

print(ceil(1.8))
print(pi)

Но при таком импорте мы можем столкнуться с ситуацией, когда импортируемая функция (или переменная) переопределяется в нашей программе. Например, если прописать свою собственную функцию ceil:

def ceil(x):
    print("своя функция ceil")
    return x

то именно она и будет вызвана, потому что сначала происходит импорт, а затем, объявление функции. Если объявление функции сделать до импорта, то, наоборот, будет использована библиотечная функция, а наша затрется. То есть, берется то, что определяется последним.

Для разрешения такой ситуации (конфликта имен) можно у импортируемых элементов указывать псевдонимы через ключевое слово as:

from math import ceil as m_ceil, pi

И, далее, уже обращаться к функции ceil через имя m_ceil:

print(m_ceil(1.8))

Конструкция from позволяет выполнять импорт сразу всего пространства имен, если после import поставить *:

from math import *

Тогда все функции, переменные и другие объекты будут напрямую импортированы в нашу программу, что также может вызвать конфликт имен, в частности, сейчас это происходит с функцией ceil. Поэтому делать такой импорт крайне не рекомендуется. Мы даже наперед точно не сможем сказать, какие имена будут добавлены в этом случае, особенно, если библиотеки меняются от версии к версии. Так что лучше такой импорт вообще не делать в своих программах.

И еще один момент. Формально в импорте мы можем через запятую перечислять имена импортируемых модулей, например:

import pprint, time, random

но стандарт PEP8 так делать не рекомендует. Следует вместо одного такого импорта записывать три, каждый с новой строчки:

import pprint
import time
import random

Это правило не касается конструкции from … import … Здесь, конечно же, мы указываем конкретные имена через запятую.

Наконец, последняя рекомендация – располагать импорты в самом начале программы. Редко от этого правила отступают, но в большинстве случаев импортирование следует делать в первых строчках программы.

На этом мы с вами завершим первое знакомство с модулями языка Python. Надеюсь, теперь вы знаете, как выполнять импорт стандартных библиотек. На следующем занятии мы продолжим эту тему и поговорим о создании и импорте собственных модулей.

Курс по Python: https://stepik.org/course/100707

Видео по теме