Математический анализ. 3е издание
Скачать 4.86 Mb.
|
Использование модулей Клиенты могут использовать простой файл модуля, только что напи санный нами, выполнив инструкцию import или from. Обе инструкции отыскивают, компилируют и запускают программный код модуля, ес Использование модулей 503 ли он еще не был загружен. Главное различие этих инструкций заклю чается в том, что инструкция import загружает модуль целиком, поэто му при обращении к именам в модуле их необходимо дополнять име нем модуля. Инструкция from, напротив, загружает (или копирует) из модуля отдельные имена. Посмотрим, что это означает на примере программного кода. Все сле дующие примеры вызывают функцию printer, определенную во внеш нем модуле module1.py, но делают это различными способами. Инструкция import В первом примере имя module1 служит двум различным целям – оно идентифицирует внешний файл, который должен быть загружен, и пре вращается в имя переменной, которая ссылается на объект модуля по сле загрузки файла: >>> import module1 # Загрузить модуль целиком >>> module1.printer('Hello world!') # Имя дополняется именем модуля Hello world! Так как в результате выполнения инструкции import в сценарии появ ляется имя, ссылающееся на полный объект модуля, нам необходимо использовать имя модуля при обращении к его атрибутам (например, module1.printer ). Инструкция from Напротив, инструкция from копирует имена из области видимости од ного файла в область видимости другого, что позволяет непосредствен но использовать скопированные имена, не предваряя их именем моду ля (например, printer): >>> from module1 import printer # Копировать одну переменную >>> printer('Hello world!') # Имя не требует дополнения Hello world! Этот пример дает тот же результат, что и предыдущий, но так как им портируемое имя копируется в область видимости, в которой находит ся сама инструкция from, можно напрямую обращаться к переменной в сценарии, не предваряя его именем вмещающего модуля. Как будет показано далее, инструкция from является всего лишь не большим расширением инструкции import – она импортирует файл мо дуля как обычно, но выполняет дополнительный шаг, на котором ко пирует одно или более имен из импортируемого файла. Инструкция from * Наконец, в следующем примере используется специальная форма ин струкции from: когда используется символ *, копируются все имена, ко торым присваиваются значения на верхнем уровне указанного модуля. 504 Глава 19. Основы программирования модулей В этом случае точно так же можно использовать скопированное имя printer , не предваряя его именем модуля: >>> from module1 import * # Скопировать все переменные >>> printer('Hello world!') Hello world! С технической точки зрения обе инструкции, from и import, вызывают одну и ту же операцию импорта, просто форма from * дополнительно выполняет копирование всех имен в импортируемом модуле в область видимости, откуда производится импорт. По сути происходит совме щение пространств имен модулей, что позволяет нам меньше вводить с клавиатуры. Как видите, модули действительно легко использовать. Чтобы еще лучше понять, что присходит в действительности, когда вы определяе те и используете модули, рассмотрим некоторые их свойства более подробно. Импорт выполняется только один раз Один из самых типичных вопросов, которые задают начинающие про граммисты, начав использовать модули: «Почему операция импорта перестает работать?». Они часто сообщают, что при первой попытке импортировать модуль все работает, но последующие попытки импор та в интерактивной оболочке (или во время работы программы) не да ют должного эффекта. В действительности такой эффект и не предпо лагается, и вот почему. Модули загружаются и запускаются первой и только первой инструк цией import или from. Реализовано такое поведение преднамеренно, по тому что импортирование – это дорогостоящая операция и интерпре татор выполняет ее всего один раз за все время работы. Последующие операции импорта просто получают объект уже загруженного модуля. Из этого следует: так как программный код на верхнем уровне модуля выполняется всего один раз, это обстоятельство можно использовать для инициализации переменных. Рассмотрим пример модуля simple.py: print 'hello' spam = 1 # Инициализировать переменную В этом примере инструкции print и = выполняются при первой опера ции импортирования модуля, и переменная spam инициализируется во время импортирования: % python >>> import simple # Первая инструкция import: загружает # и запускает код модуля hello >>> simple.spam # Операция присваивания создает атрибут 1 Использование модулей 505 Вторая и все последующие операции импортирования не приводят к перезапуску программного кода модуля – они просто получают объ ект модуля из внутренней таблицы модулей интерпретатора. В резуль тате повторная инициализация переменной spam не происходит: >>> simple.spam = 2 # Изменить атрибут модуля >>> import simple # Просто получает уже загруженный модуль >>> simple.spam # Код не перезапускается: атрибут не изменился 2 Конечно, иногда действительно бывает необходимо перезапустить программный код модуля при повторных операциях импортирования. Позднее в этой главе мы увидим, как это можно сделать с помощью функции reload. Инструкции import и from – операции присваивания Так же, как и инструкция def, инструкции import и from являются вы полняемыми инструкциями, а не объявлениями времени компиля ции. Они могут вкладываться в условные инструкции if, присутство вать в объявлениях функций def и т. д., и они не имеют никакого эф фекта, пока интерпретатор не достигнет их в ходе выполнения про граммы. Другими словами, импортируемые модули и имена в них не будут доступны, пока не будут выполнены соответствующие инструк ции import или from. Кроме того, подобно инструкции def, import и from – это явные операции присваивания: • Инструкция import присваивает ссылку на объект модуля един ственной переменной. • Инструкция from присваивает одно или более имен объектам с теми же именами в другом модуле. Все, что уже обсуждалось ранее, в равной степени применимо и к мо дулям. Например, имена, копируемые инструкцией from, становятся ссылками на разделяемые объекты – как и в случае с аргументами функций, переприсваивание полученному имени не оказывает воздей ствия на модуль, откуда это имя было скопировано, но изменение из+ меняемого объекта может оказывать воздействие на объект в модуле, откуда он был импортирован. Для иллюстрации рассмотрим следую щий файл small.py: x = 1 y = [1, 2] % python >>> from small import x, y # Скопировать два имени >>> x = 42 # Изменяется только локальная переменная x >>> y[0] = 42 # Изменяется непосредственно изменяемый объект Здесь x не является разделяемым изменяемым объектом, а вот y – яв ляется. Имена y в импортирующем и импортируемом модулях ссыла ются на один и тот же объект списка, поэтому изменения, произведен ные в одном модуле, будут видны в другом модуле: 506 Глава 19. Основы программирования модулей >>> import small # Получить имя модуля (инструкция from его не дает) >>> small.x # x в small – это не моя переменная x 1 >>> small.y # Но изменяемый объект используется совместно [42, 2] Чтобы увидеть графическое изображение того, что делает со ссылками инструкция from, вернитесь к рис. 16.2 (передача аргументов функци ям) и мысленно замените слова «вызывающая программа» и «функ ция» на «импортируемый модуль» и «импортирующий модуль». Эф фект тот же самый, за исключением того, что здесь мы имеем дело с именами в модулях, а не с функциями. Операция присваивания вез де в языке Python работает одинаково. Изменение значений имен в других файлах Вспомним, что в предыдущем примере присваивание переменной x в интерактивной оболочке изменяло ее значение только в этой области видимости и не оказывало влияния на переменную x в файле – между именем, скопированным инструкцией from, и именем в файле, откуда это имя было скопировано, нет никакой связи. Чтобы действительно изменить глобальное имя в другом файле, необходимо использовать инструкцию import: % python >>> from small import x, y # Скопировать два имени >>> x = 42 # Изменить только локальное имя x >>> import small # Получить имя модуля >>> small.x = 42 # Изменить x в другом модуле Это явление было описано в главе 16. Поскольку изменение перемен ных в других модулях, как в данном случае, часто является источни ком проблем (и следствием неудачного проектирования), мы еще вер немся к этому приему позднее в этой части книги. Обратите внимание, что изменение элемента y[0] в предыдущем примере – это нечто иное; изменяется объект, а не имя. Эквивалентность инструкций import и from Обратите внимание: в предыдущем примере после инструкции from нам потребовалось выполнить инструкцию import, чтобы получить доступ к имени модуля small, – инструкция from копирует только име на из одного модуля в другой и ничего не присваивает самому имени модуля. Инструкция from, приведенная ниже: from module import name1, name2 # Копировать только эти два имени эквивалентна следующей последовательности, по крайней мере, кон цептуально: import module # Получить объект модуля Использование модулей 507 name1 = module.name1 # Скопировать имена с помощью присваивания name2 = module.name2 del module # Удалить имя модуля Как и все операции присваивания, инструкция from создает новые пе ременные в импортирующем модуле, которые ссылаются на объекты с теми же именами в импортируемом файле. При этом копируются только имена, а не сам модуль. При использовании формы from * этой инструкции (from module import *) эквивалентная последовательность действий та же самая, только при этом копируются все имена, опреде ленные на верхнем уровне импортируемого модуля. Обратите внимание, что на первом шаге инструкция from выполняет обычную операцию import. Вследствие этого инструкция from всегда импортирует весь модуль целиком, если он еще не был импортирован, независимо от того, сколько имен копируется из файла. Нет никакой возможности загрузить только часть модуля (например, только одну функцию), но так как модули – это байткод, а не машинный код, влияние на производительность оказывается незначительным. Потенциальные проблемы инструкции from Инструкция from делает местоположение переменных менее явным и оче видным (имя name несет меньше информации, чем module.name), поэтому некоторые пользователи Python рекомендуют использовать инструк цию import вместо from. Однако я не уверен, что это такой уж однознач ный совет: инструкция from используется достаточно часто и без каких либо страшных последствий. На практике часто бывает удобно изба виться от необходимости набирать имя модуля всякий раз, когда требу ется использовать один из его инструментов. Это особенно справедливо для крупных модулей, которые предоставляют большое число атрибу тов, таких как модуль Tkinter из стандартной библиотеки, например. Суть проблемы состоит в том, что инструкция from способна повреждать пространства имен, по крайней мере, в принципе – если использовать ее для импортирования переменных, когда существуют одноименные переменные в имеющейся области видимости, то эти переменные про сто будут перезаписаны. Эта проблема отсутствует при использовании инструкции import, потому что доступ к содержимому импортируемого модуля возможен только через его имя (имя module.attr не конфликтует с именем attr в текущей области видимости). Пока вы понимаете и кон тролируете все, что может происходить при использовании инструкции from , во всем этом нет большой проблемы, особенно если импортируе мые имена указываются явно (например, from module import x, y, z). С другой стороны, инструкция from скрывает в себе более серьезные проблемы, когда используется в комбинации с функцией reload, т. к. импортированные имена могут ссылаться на предыдущие версии объ ектов. Кроме того, инструкция в форме from module import * действи тельно может повреждать пространства имен и затрудняет понимание 508 Глава 19. Основы программирования модулей имен, особенно когда она применяется более чем к одному файлу. В этом случае нет никакого способа определить, какому модулю при надлежит то или иное имя, разве только выполнить поиск по файлам с исходными текстами. В действительности форма from * вставляет од но пространство имен в другое, что сводит на нет преимущества, кото рые несет возможность разделения пространств имен. Мы будем рас сматривать эти проблемы более подробно в разделе «Типичные ошиб ки при работе с модулями» в конце этой части книги (глава 21). Пожалуй, лучший совет, который можно дать, – в общем отдавать предпочтение инструкции import для простых модулей, явно перечис лять необходимые переменные в инструкциях from и не использовать форму from * для импорта более чем одного файла в модуле. При таком подходе можно предполагать, что все неопределенные имена распола гаются в модуле, к которому обращались через инструкцию from *. При работе с инструкцией from, конечно, следует проявлять осторож ность, но, вооруженные знаниями, большинство программистов нахо дят ее удобной для организации доступа к модулям. Когда необходимо использовать инструкцию import Единственное, когда необходимо вместо инструкции from использо вать инструкцию import, – когда требуется использовать одно и то же имя, присутствующее в двух разных модулях. Например, когда два файла поразному определяют одно и то же имя: # M.py def func(): ...выполнить чтото одно... # N.py def func(): ...выполнить чтото другое... и необходимо использовать обе версии имени в программе. В этом слу чае инструкцию from использовать нельзя, потому что в результате вы получите единственное имя в вашей области видимости: # O.py from M import func from N import func # Перезапишет имя, импортированное из модуля M func() # Будет вызвана N.func Зато можно использовать инструкцию import, потому что включение имени вмещающего модуля сделает имена уникальными: # O.py import M, N # Получить модуль целиком, а не отдельные имена M.func() # Теперь можно вызывать обе функции N.func() # Наличие имени модуля делает их уникальными Этот случай достаточно необычен, поэтому вы вряд ли часто будете сталкиваться с ним на практике. Пространства имен модулей 509 Пространства имен модулей Модули будут, вероятно, более понятны, если представлять их, как простые пакеты имен – то есть место, где определяются переменные, которые должны быть доступны остальной системе. С технической точки зрения каждому модулю соответствует отдельный файл, и ин терпретатор создает объект модуля, содержащий все имена, которым присвоены какиелибо значения в файле модуля. Проще говоря, моду ли – это всего лишь пространства имен (места, где создаются имена), и имена, находящиеся в модуле, называются его атрибутами. В этом разделе мы исследуем, как работает этот механизм. Файлы создают пространства имен Итак, как же файлы трансформируются в пространства имен? Суть в том, что каждое имя, которому присваивается некоторое значение на верхнем уровне файла модуля (то есть не вложенное в функции или в классы), превращается в атрибут этого модуля. Например, операция присваивания, такая как X = 1, на верхнем уров не модуля M.py, превращает имя X в атрибут модуля M, обратиться к которому изза пределов модуля можно как M.X. Кроме того, имя X ста новится глобальной переменной для программного кода внутри M.py, но нам необходимо более формально объяснить понятия загрузки мо дуля и областей видимости, чтобы понять почему: • Инструкции модуля выполняются во время первой попытки им! порта. Когда модуль импортируется в первый раз, интерпретатор Python создает пустой объект модуля и выполняет инструкции в мо дуле одну за другой, от начала файла до конца. • Операции присваивания, выполняемые на верхнем уровне, созда! ют атрибуты модуля. Во время импортирования инструкции при сваивания выполняемые на верхнем уровне файла и не вложенные в инструкции def или class (например, =, def) создают атрибуты объек та модуля – при присваивании имена сохраняются в пространстве имен модуля. • Доступ к пространствам имен модулей можно получить через атри! буты __dict__ или dir(M). Пространства имен модулей, создаваемые операцией импортирования, представляют собой словари – доступ к ним можно получить через встроенный атрибут __dict__, ассоции рованный с модулем, и с помощью функции dir. Функция dir – это примерный эквивалент отсортированного списка ключей атрибута __dict__ , но она включает унаследованные имена классов, может воз вращать не полный список и часто изменяется от версии к версии. • Модуль – это единая область видимости (локальная является гло! бальной). Как мы видели в главе 16, имена на верхнем уровне моду ля подчиняются тем же правилам обращения/присваивания, что имена в функциях, только в этом случае локальная область видимо 510 Глава 19. Основы программирования модулей сти совпадает с глобальной (точнее, они следуют тому же правилу LEGB поиска в областях видимости, с которым мы познакомились в главе 16, только без уровней поиска L и E). Но в модулях область видимости модуля после загрузки модуля превращается в атрибут словарь объекта модуля. В отличие от функций (где локальное про странство имен существует только во время выполнения функции), область видимости файла модуля превращается в область видимо сти атрибутов объекта модуля и никуда не исчезает после выполне ния операции импортирования. Ниже эти понятия демонстрируются в программном коде. Предполо жим, что мы создаем в текстовом редакторе следующий файл модуля с именем module2.py: print 'starting to load...' import sys name = 42 def func(): pass class klass: pass print 'done loading.' Когда модуль будет импортироваться в первый раз (или будет запущен как программа), интерпретатор выполнит инструкции модуля от нача ла до конца. В ходе операции импортирования одни инструкции созда ют имена в пространстве имен модуля, а другие выполняют определен ную работу. Например, две инструкции print в этом файле выполня ются во время импортирования: >>> |