Курс по Python: https://stepik.org/course/100707
Этим занятием мы открываем новую тему, связанную с модулями и пакетами. В некоторых программах
этого курса я уже делал импорт стандартных модулей, например:
чтобы
использовать их функции. Но что они из себя представляют? В действительности,
модуль – это обычный текстовый файл программы на языке Python. В этом легко
убедиться, если в PyCharm нажать и удерживать клавишу Ctrl и щелкнуть по
имени модуля, например, math. Откроется файл и мы можем ознакомиться
с его содержимым.
Второй вопрос, а
что собственно делает конструкция import? Как он
импортирует этот текст программы в нашу программу? Давайте я с помощью функции locals() выведу все
локальные переменные нашей программы:
В консоли у нас
появился словарь и последними записями в нем идут имена math и time, которые ссылаются
на соответствующие импортированные модули. Для более читаемого вида этой
информации я импортирую еще один модуль:
и из него вызову
функцию с тем же именем:
Теперь мы видим
все гораздо нагляднее. Кстати, дополнительно появилась еще одна строчка с
именем pprint после его
импортирования. Так вот, все эти имена: math, pprint, time – это
переменные в нашей программе и каждая ссылается на свое пространство имен, со
своими глобальными переменными. Например, чтобы посмотреть, что содержит модуль
math, можно получить
все ее переменные с помощью функции dir:
Мы видим полный
список глобальных атрибутов этого модуля, включая имена функций и переменных.
То есть, чтобы обратиться к определенной функции в своей программе, нам нужно
написать имя импортируемого модуля и через точку указать имя функции или
переменной, например:
a = math.ceil(1.8)
print(a)
print(math.pi)
То есть, в
сточке import math автоматически
создается пространство имен math в нашей программе, через которое мы
можем обращаться к любому глобальному атрибуту этого модуля. И так с каждым
импортируемым модулем.
Все эти модули,
что я использовал, поставляются вместе с языком Python и составляют
его стандартную библиотеку. Что еще входит в нее? Полный список модулей и
подробное их описание приведено на странице официальной документации:
https://docs.python.org/3/library/
Я рекомендую вам
в целом с ней ознакомиться, чтобы представлять ее возможности и использовать в
своей программе готовый функционал, а не изобретать собственные велосипеды.
Далее,
предположим, что мы в своей программе используем переменную с именем:
В итоге, в нашей
программе, сначала при импорте math будет создана глобальная переменная math на
импортируемый модуль, а затем, эта переменная станет ссылаться на строку. В
результате мы уже не можем воспользоваться модулем math в своей
программе и попытки обратиться к функции или переменной приведут к ошибкам.
Как разрешить
эту ситуацию? Язык Python позволяет нам в момент импорта указывать
псевдонимы импортируемых модулей, используя ключевое слово as, например:
И, далее, по
программе использовать переменную mt в качестве имени модуля. На
практике такая подстановка выполняется в двух целях. Во-первых, чтобы избежать
возможного конфликта имен в программе и, во-вторых, для удобства, если имя
модуля слишком длинное, то имеет смысл записать его более короткий псевдоним.
Когда
импортируется модуль через import, то автоматически подключается
все его пространство имен к нашей программе. Однако, часто из всего этого
многообразия используется всего несколько функций или переменных. И, если мы не
хотим подключать модуль целиком, а сделать выборочный импорт некоторых его
атрибутов, то для этого следует использовать другую конструкцию:
from math import ceil, pi
Смотрите,
теперь, при выводе:
мы не видим имя
модуля 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:
Конструкция from позволяет
выполнять импорт сразу всего пространства имен, если после import поставить *:
Тогда все
функции, переменные и другие объекты будут напрямую импортированы в нашу
программу, что также может вызвать конфликт имен, в частности, сейчас это
происходит с функцией ceil. Поэтому делать такой импорт крайне не рекомендуется.
Мы даже наперед точно не сможем сказать, какие имена будут добавлены в этом
случае, особенно, если библиотеки меняются от версии к версии. Так что лучше
такой импорт вообще не делать в своих программах.
И еще один
момент. Формально в импорте мы можем через запятую перечислять имена
импортируемых модулей, например:
import pprint, time, random
но стандарт PEP8 так делать не
рекомендует. Следует вместо одного такого импорта записывать три, каждый с
новой строчки:
import pprint
import time
import random
Это правило не
касается конструкции from … import … Здесь,
конечно же, мы указываем конкретные имена через запятую.
Наконец,
последняя рекомендация – располагать импорты в самом начале программы. Редко от
этого правила отступают, но в большинстве случаев импортирование следует делать
в первых строчках программы.
На этом мы с
вами завершим первое знакомство с модулями языка Python. Надеюсь,
теперь вы знаете, как выполнять импорт стандартных библиотек. На следующем
занятии мы продолжим эту тему и поговорим о создании и импорте собственных
модулей.
Курс по Python: https://stepik.org/course/100707