Теория урока

67. Написание модулей в Python

Оглавление урока

Введение

В предыдущем уроке мы начали знакомство с модулями. Хотя, как начали, продолжили более глубокое изучение, так как неоднократно с ними уже встречались.

В этом уроке мы что-то повторим, а какие-то темы будут для вас новыми: область видимости, вложение, перезагрузка и т.п.

Чтобы создать модуль в Python, откройте текстовый файл и напишите там какой-нибудь код на Python. После чего сохранить его с расширением .py. Имя модуля может быть практически любым. Например, нельзя назвать модуль if.py или использовать в имени другое зарезервированное слово, так как импортирование оператором import модуля с таким именем приведет к ошибке. Именование модулей и каталогов подчиняется правилам создания имен для переменных (если забыли, то вернитесь к уроку «Переменные и комментарии в Python»).

Использование модулей

Использовать только что написанный модуль можно сразу при помощи операторов import и from. С первым мы уже разобрались. Второй работает практически также, но в отличие от первого, который импортирует модуль как единое целое, оператор from извлекает только необходимые «функциональные части» модуля. Далее рассмотрим пример, файл a.py выглядит следующим образом:

Пример
import b
b.hello()

Модуль b.py представлен ниже:

Пример
def hello():
print('Привет из модуля b.py')

Работа оператора import уже вам знакома из предыдущего урока. Теперь извлечем только часть из модуля – атрибут hello().

Пример
from b import hello
hello()

Таким образом, мы применяем в сценарии скопированное имя hello() напрямую, не указывая на объект b, как в предыдущем примере. Оператор from работает так же, как и import (выполняет трехшаговую процедуру из предыдущего урока), добавляя один свой «шаг» - копирование одного или более имен из файла модуля. Чтобы импортировать несколько имен, необходимо их перечислить через запятую:

Пример
from b import hello, func1, func2

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

Пример
from b import *
hello()

Операторы from и import являются исполняемыми, а значит их можно помещать в условные конструкции if, внутрь функций, использовать в операторах try (урок про исключения «Обработка исключений (try/except) в Python») и так далее.

Имена, копируемые оператором from, становятся ссылками на соответствующие объекты. Про то, как происходит присваивание в Python, мы говорили, например, здесь: «Типы данных в Python». С модулями точно так же. Рассмотрим пример:

Пример
'''  a.py  '''
from b import *

print_x() # => 10
print_y() # => [1, 2]

x = 20
y[1] = 30

print_x() # => 10
print_y() # => [1, 30]

И модуль b.py:

Пример
'''  b.py  '''
x = 10
y = [1, 2]

def print_x():
print(x)

def print_y():
print(y)

Как видите, мы присвоили в файле верхнего уровня объекту y, который ссылается на y из модуля, другое значение для элемента с индексом 1 (более подробно об этом было в разделе «Копирование списков» в уроке «Конкатенация и сортировка списков в Python»).

Оставим модуль b.py без изменений и подключим его при помощи оператора import.

Пример
'''  a.py  '''
import b

b.print_x() # => 10
b.print_y() # => [1, 2]

b.x = 20
b.y[1] = 30

b.print_x() # => 20
b.print_y() # => [1, 30]

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

Согласен, сложно это понять сходу, поэтому перепишем импортирование в предыдущем примере (from b import *) вот так:

Пример
import b
x = b.x
y = b.y
print_x = b.print_x
print_y = b.print_y
del b

Еще раз вернувшись к разделу «Модель данных» урока «Типы данных в Python» и прочитав, как работает операция присвоения в Python, у вас сложится более хорошее понимание отличия операторов import и from … *. Как видите, оператор from импортирует целый модуль, независимо от количества необходимых имен.

Сначала могло показаться, что оператор from улучшает производительность кода, теперь, после того, как вы разобрались с импортированием при помощи from, вероятно, задумались об обратном. Но на самом деле, особой разницы в производительности нет.

Еще про трудности, связанные с from и import

Оператор from делает переменные из модуля менее явными в коде (если вы читаете код, то проще понять его, когда написано имя.модуль, а не просто имя). Из-за этого некоторые энтузиасты рекомендуют использовать оператор import, вместо from. Лично я не считаю такой совет полезным, так как на практике удобней не набирать имя модуля каждый раз при использовании его инструментов, особенно это касается больших модулей.

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

Так же оператор from может добавить проблем в совокупности с функцией reload.

Выбор за вами. Рекомендую отдавать предпочтение оператору import перед from для простых модулей, а также для последнего явно перечислять требуемые переменные через запятую и не злоупотреблять второй формой оператора from … *. А вот в случае необходимости использования одного и того же имени из разных модулей, оператор import обязателен, так как from здесь уже точно не подойдет.

Пространства имен модулей

В предыдущем уроке мы определили: модуль – изолированное хранилище для имен, а имена в модуле называются атрибутами. Как происходит «создание» пространства имен. Все имена на верхнем уровне файла становятся его атрибутами (переменные внутри тела функции или класса таковыми не являются).

Доступ к пространству имен модуля можно получить при помощи функции dir():

Пример
'''  a.py  '''
import b
print(dir(b))
Или атрибут __dict__:

''' a.py '''
import b
print(b.__dict__) # b.__dict__.keys() для вывода только ключей

Как вы поняли, пространство имен модуля хранится как объект словаря:

Пример
'''  a.py  '''
import b
print(b.__dict__['print_x']) # => <function print_x at 0x0000020E6EBDD310>

Это обычные словари, с которыми вы научились работать, начиная с урока «Словари в Python».

Область видимости и импортирование

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

Перезагрузка модулей

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

Пример
'''  a.py  '''
import b
print(b.y) # => [1, 2]

b.y[1] = 20
print(b.y) # => [1, 20]

from importlib import reload

reload(b)
print(b.y) # => [1, 2]

Обратите внимание, функцию reload() необходимо импортировать из библиотеки importlib для Python 3.4 и выше. В ранних версиях эта функция находилась в модуле imp, а версии Python 2 была встроенной.

Наш урок подошел к концу. В нем мы рассмотрели важные особенности написания модулей в Python, познакомились с операторами import и from, а также функцией reload(). Разобрались с пространствами имен и уяснили, когда импортировать при помощи оператора import, а когда при помощи оператора from.

В следующем уроке мы расширим наши знания представлением операций импортирования пакетов, которые могут предотвратить конфликты одинаковых имен в разных модулях.

ПРОЧИТАНО
Следующий урок

Похожие уроки и записи блога

Продолжаем написание классов в PythonЗнакомство с Python
Модули в PythonЗнакомство с Python
Обработка исключений (try/except) в PythonЗнакомство с Python
Типы данных в PythonЗнакомство с Python
Первое знакомство с PythonЗнакомство с Python
Еще о возможностях модулей в Python Знакомство с Python
Работа с файлами в Python Знакомство с Python
Генераторы и оператор yield в PythonЗнакомство с Python
Основы функций в PythonЗнакомство с Python
<
×
>
Впервые на сайте Codebra?

Извините за это всплывающее окно, меня они тоже раздражают.

Образовательный ресурс codebra.ru полностью посвящен программированию. Все курсы и уроки находятся на главной странице. Ради интереса можете посмотреть на содержимое курсов по Python, HTML и CSS, JavaScript, C++ и другие, размещенные на главной странице.

Если что-то не нашли, то воспользуйтесь поиском по сайту, который находится на главной странице в самом верху.

Удачи в обучении!

Закрыть окно