Модули¶
Как можно использовать код повторно, помещая его в функции, мы уже видели. А что, если нам понадобится повторно использовать различные функции в других наших программах? Как вы уже, наверное, догадались, ответ – модули.
Существуют разные способы составления модулей, но самый простой – это создать
файл с расширением .py
, содержащий функции и переменные.
Другой способ – написать модуль на том языке программирования, на котором написан сам интерпретатор Python. Например, можно писать модули на языке программирования C, которые после компиляции могут использоваться стандартным интерпретатором Python.
Модуль можно импортировать в другую программу, чтобы использовать функции из него. Точно так же мы используем стандартную библиотеку Python. Сперва посмотрим, как использовать модули стандартной библиотеки.
Пример: (сохраните как using_sys.py
)
import sys
print('Аргументы командной строки:')
for i in sys.argv:
print(i)
print('\n\nПеременная PYTHONPATH содержит', sys.path, '\n')
Вывод:
$ python3 using_sys.py we are arguments
Аргументы командной строки:
using_sys.py
we
are
arguments
Переменная PYTHONPATH содержит ['', 'C:\\Windows\\system32\\python30.zip',
'C:\\Python30\\DLLs', 'C:\\Python30\\lib',
'C:\\Python30\\lib\\plat-win', 'C:\\Python30',
'C:\\Python30\\lib\\site-packages']
Как это работает:
В начале мы импортируем модуль
sys
командойimport
. Этим мы говорим Python, что хотим использовать этот модуль. Модульsys
содержит функции, относящиеся к интерпретатору Python и его среде, т.е. к системе (system).Когда Python выполняет команду
import sys
, он ищет модульsys
. В данном случае это один из встроенных модулей, и Python знает, где его искать.Если бы это был не скомпилированный модуль, т.е. модуль, написанный на Python, тогда интерпретатор Python искал бы его в каталогах, перечисленных в переменной
sys.path
. Если модуль найден, выполняются команды в теле модуля, и он становится доступным. Обратите внимание, что инициализация[1] происходит только при первом импорте модуля.Доступ к переменной
argv
в модулеsys
предоставляется при помощи точки, т.е.sys.argv
. Это явно показывает, что это имя является частью модуляsys
. Ещё одним преимуществом такого обозначения является то, что имя не конфликтует с именем переменнойargv
, которая может использоваться в вашей программе.Переменная
sys.argv
является списком строк (списки будут детально обсуждаться в одной из последующих глав). Она содержит список аргументов командной строки, т.е. аргументов, переданных программе из командной строки.Если вы используете среду разработки[2] для написания и запуска программ, поищите где-нибудь в её меню возможность передавать параметры командной строки.
В нашем примере, когда мы запускаем “
python using_sys.py we are arguments
”, мы запускаем модульusing_sys.py
командойpython
, а всё, что следует далее – аргументы, передаваемые программе[3]. Python сохраняет аргументы командной строки в переменнойsys.argv
для дальнейшего использования.Помните, что имя запускаемого сценария[4] всегда является первым аргументом в списке
sys.argv
. Так что в приведённом примере'using_sys.py'
будет элементомsys.argv[0]
,'we'
–sys.argv[1]
,'are'
–sys.argv[2]
, а'arguments'
–sys.argv[3]
. Помните, что в Python нумерация начинается с 0, а не с 1.
sys.path
содержит список имён каталогов, откуда импортируются модули. Заметьте, что первая строка вsys.path
пуста; эта пустая строка показывает, что текущая директория также является частьюsys.path
, которая совпадает со значением переменной окруженияPYTHONPATH
. Это означает, что модули, расположенные в текущем каталоге, можно импортировать напрямую. В противном случае придётся поместить свой модуль в один из каталогов, перечисленных вsys.path
.Помните, что текущий каталог – это каталог, в котором была запущена программа. Выполните “
import os; print(os.getcwd())
”, чтобы узнать текущий каталог программы.
Файлы байткода .pyc¶
Импорт модуля – относительно дорогостоящее мероприятие, поэтому Python
предпринимает некоторые трюки для ускорения этого процесса. Один из способов –
создать байт-компилированные файлы (или байткод) с расширением .pyc
,
которые являются некой промежуточной формой, в которую Python переводит
программу (помните раздел “Введение” о том, как
работает Python?). Такой файл .pyc
полезен при импорте модуля в следующий
раз в другую программу – это произойдёт намного быстрее, поскольку значительная
часть обработки, требуемой при импорте модуля, будет уже проделана. Этот
байткод также является платформо-независимым.
Примечание
Обычно файлы .pyc
создаются в том же каталоге, где расположены и
соответствующие им файлы .py
. Если Python не может получить доступ для
записи файлов в этот каталог, файлы .pyc
созданы не будут.
Оператор from ... import ...¶
Чтобы импортировать переменную argv
прямо в программу и не писать всякий
раз sys.
при обращении к ней, можно воспользоваться выражением
“from sys import argv
”.
Для импорта всех имён, использующихся в модуле sys
, можно выполнить
команду “from sys import *
”. Это работает для любых модулей.
В общем случае вам следует избегать использования этого оператора и
использовать вместо этого оператор import
, чтобы предотвратить конфликты
имён и не затруднять чтение программы.
Пример:
from math import *
n = int(input("Введите диапазон:- "))
p = [2, 3]
count = 2
a = 5
while (count < n):
b=0
for i in range(2,a):
if ( i <= sqrt(a)):
if (a % i == 0):
print(a,"непростое")
b = 1
else:
pass
if (b != 1):
print(a,"простое")
p = p + [a]
count = count + 1
a = a + 2
print(p)
Имя модуля – __name__¶
У каждого модуля есть имя, и команды в модуле могут узнать имя их модуля. Это
полезно, когда нужно знать, запущен ли модуль как самостоятельная программа или
импортирован. Как уже упоминалось выше, когда модуль импортируется впервые,
содержащийся в нём код исполняется. Мы можем воспользоваться этим для того,
чтобы заставить модуль вести себя по-разному в зависимости от того, используется
ли он сам по себе или импортируется в другую программа. Этого можно достичь с
применением атрибута модуля под названием __name__
.
Пример: (сохраните как using_name.py
)
if __name__ == '__main__':
print('Эта программа запущена сама по себе.')
else:
print('Меня импортировали в другой модуль.')
Вывод:
$ python3 using_name.py
Эта программа запущена сама по себе.
$ python3
>>> import using_name
Меня импортировали в другой модуль.
>>>
Как это работает:
В каждом модуле Python определено его имя –__name__
[5] . Если оно равно'__main__'
, это означает, что модуль запущен самостоятельно пользователем, и мы можем выполнить соответствующие действия.
Создание собственных модулей¶
Создать собственный модуль очень легко. Да вы всё время делали это!
Ведь каждая программа на Python также является и модулем. Необходимо лишь
убедиться, что у неё установлено расширение .py
. Следующий пример объяснит
это.
Пример: (сохраните как mymodule.py
)
def sayhi():
print('Привет! Это говорит мой модуль.')
__version__ = '0.1'
# Конец модуля mymodule.py
Выше приведён простой модуль. Как видно, в нём нет ничего особенного по сравнению с обычной программой на Python. Далее посмотрим, как использовать этот модуль в других наших программах.
Помните, что модуль должен находиться либо в том же каталоге, что и программа,
в которую мы импортируем его, либо в одном из каталогов, указанных в
sys.path
.
Ещё один модуль (сохраните как mymodule_demo.py
):
import mymodule
mymodule.sayhi()
print ('Версия', mymodule.__version__)
Вывод:
$ python mymodule_demo.py
Привет! Это говорит мой модуль.
Версия 0.1
Как это работает:
Обратите внимание, что мы используем всё то же обозначение точкой для доступа к элементам модуля. Python повсеместно использует одно и то же обозначение точкой, придавая ему таким образом характерный “Python-овый” вид и не вынуждая нас изучать всё новые и новые способы делать что-либо.
Вот версия, использующая синтаксис from..import
(сохраните как
mymodule_demo2.py
):
from mymodule import sayhi, __version__
sayhi()
print('Версия', __version__)
Вывод mymodule_demo2.py
такой же, как и mymodule_demo.py
.
Обратите внимание, что если в модуле, импортирующем данный модуль, уже было
объявлено имя __version__
, возникнет конфликт. Это весьма вероятно, так как
объявлять версию любого модуля при помощи этого имени – общепринятая практика.
Поэтому всегда рекомендуется отдавать предпочтение оператору import
, хотя
это и сделает вашу программу немного длиннее.
Вы могли бы также использовать:
from mymodule import *
Это импортирует все публичные имена, такие как sayhi
, но не импортирует
__version__
, потому что оно начинается с двойного подчёркивания
Дзэн Python
Одним из руководящих принципов в Python является “Явное лучше Неявного”.
Выполните команду “import this
”, чтобы узнать больше, а также
просмотрите
это обсуждение,
в котором приводятся примеры по каждому из принципов.
Функция dir¶
Встроенная функция dir()
возвращает список имён, определяемых объектом.
Например, для модуля в этот список входят функции, классы и переменные,
определённые в этом модуле.
Эта функция может принимать аргументы. Если в качестве аргумента указано имя модуля, она возвращает список имён, определённых в этом модуле. Если никакого аргумента не передавать, она вернёт список имён, определённых в текущем модуле.
Пример:
$ python3
>>> import sys # получим список атрибутов модуля 'sys'
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__s
tderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_compact_freelists',
'_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', '
byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle'
, 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable',
'exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getfil
esystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof',
'gettrace', 'getwindowsversion', 'hexversion', 'intern', 'maxsize', 'maxunicode
', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platfor
m', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit
', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_in
fo', 'warnoptions', 'winver']
>>> dir() # получим список атрибутов текущего модуля
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
>>> a = 5 # создадим новую переменную 'a'
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'a', 'sys']
>>> del a # удалим имя 'a'
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
>>>
Как это работает:
Сперва мы видим результат применения
dir
к импортированному модулюsys
. Видим огромный список атрибутов, содержащихся в нём.Затем мы вызываем функцию
dir
, не передавая ей параметров. По умолчанию, она возвращает список атрибутов текущего модуля. Обратите внимание, что список импортированных модулей также входит туда.Чтобы пронаблюдать за действием
dir
, мы определяем новую переменнуюa
и присваиваем ей значение, а затем снова вызываемdir
. Видим, что в полученном списке появилось дополнительное значение. Удалим переменную/атрибут из текущего модуля при помощи оператораdel
, и изменения вновь отобразятся на выводе функцииdir
.Замечание по поводу
del
: этот оператор используется для удаления переменной/имени, и после его выполнения, в данном случае –del a
, к переменнойa
больше невозможно обратиться – её как будто никогда и не было.Обратите внимание, что функция
dir()
работает для любого объекта. Например, выполните “dir('print')
”, чтобы увидеть атрибуты функцииdir(str)
”, чтобы увидеть атрибуты классаstr
.
Пакеты¶
К настоящему времени вы, вероятно, начали наблюдать некоторую иерархию в организации ваших программ. Переменные обычно находятся в функциях. Функции и глобальные переменные обычно находятся в модулях. А что, если возникнет необходимость как-то организовать модули? Вот здесь-то и выходят на сцену пакеты.
Пакеты – это просто каталоги с модулями и специальным файлом __init__.py
,
который показывает Python, что этот каталог особый, так как содержит модули
Python.
Представим, что мы хотим создать пакет под названием “world” с субпакетами “asia”, “africa” и т.д., которые, в свою очередь, будут содержать модули “india”, “madagascar” и т.д.
Для этого следовало бы создать следующую структуру каталогов:
| - <некоторый каталог из sys.path>/
| |---- world/
| |---- __init__.py
| |---- asia/
| | |---- __init__.py
| | |---- india/
| | |---- __init__.py
| | |---- foo.py
| |---- africa/
| |---- __init__.py
| |---- madagascar/
| |---- __init__.py
| |---- bar.py
Пакеты – это удобный способ иерархически организовать модули. Такое часто встречается в стандартной библиотеке.
Резюме¶
Точно так же, как функции являются многократно используемыми фрагментами программ, модули являются многократно используемыми программами. Пакеты – это способ иерархической организации модулей. Стандартная библиотека Python является примером такого набора пакетов и модулей.
Мы увидели, как пользоваться этими модулями и создавать свои.
Далее мы познакомимся с некоторыми интересными концепциями, называемыми “структуры данных”.
Примечания¶
[1] | Инициализация – ряд действий, производимых при начальной загрузке (прим. перев.) |
[2] | IDE – от англ. “Integrated Development Environment” – “интегрированная среда разработки” (прим. перев.) |
[3] | “we are arguments” – англ. “мы аргументы” (прим. перев.) |
[4] | Программу на интерпретируемом языке программирования также называют сценарием или скриптом (прим. перев.) |
[5] | name - англ. “имя” (прим. перев.) |