Математический анализ. 3е издание
Скачать 4.86 Mb.
|
import module2 starting to load... done loading. Но как только модуль будет загружен, его область видимости превра тится в пространство имен атрибутов объекта модуля, который возвра щает инструкция import. После этого можно обращаться к атрибутам в этом пространстве имен, дополняя их именем вмещающего модуля: >>> module2.sys >>> module2.name 42 >>> module2.func >>> module2.klass Здесь именам sys, name, func и klass были присвоены значения во время выполнения инструкций модуля, поэтому они стали атрибутами после завершения операции импортирования. О классах мы будем говорить Пространства имен модулей 511 в шестой части книги, но обратите внимание на атрибут sys – инструк ции import действительно присваивают объекты модулей именам, а лю бая операция присваивания на верхнем уровне файла создает атрибут модуля. Внутри интерпретатора пространства имен хранятся в виде объектов словарей. Это самые обычные объекты словарей с обычными метода ми. Обратиться к словарю пространства имен модуля можно через ат рибут __dict__ модуля: >>> module2._ _dict_ _.keys() ['__file__', 'name', '__name__', 'sys', '__doc__', '__builtins__', 'klass', 'func'] Имена, которые были определены в файле модуля, становятся ключа ми внутреннего словаря, таким образом, большинство имен здесь от ражают операции присваивания на верхнем уровне в файле. Однако интерпретатор Python добавляет в пространство имен модуля еще не сколько имен, например __file__ содержит имя файла, из которого был загружен модуль, а __name__ – это имя, под которым модуль извес тен импортерам (без расширения .py и без пути к каталогу). Дополнение имен атрибутов После ознакомления с модулями мы должны поближе рассмотреть по нятие дополнения имен. В языке Python для доступа к атрибутам любо го объекта используется синтаксис дополнения имени object.attribute. Дополнение имени – это в действительности выражение, возвращаю щее значение, присвоенное имени атрибута, ассоциированного с объ ектом. Например, выражение module2.sys в предыдущем примере воз вращает значение атрибута sys в объекте module2. Точно так же, если имеется встроенный объект списка L, выражение L.append вернет метод append , ассоциированный с этим списком. Итак, какую роль играет дополнение имен атрибутов с точки зрения правил, рассмотренных нами в главе 16? В действительности – ника кую: это совершенно независимые понятия. Когда вы обращаетесь к именам, используя дополнение, вы явно указываете интерпретатору объект, атрибут которого требуется получить. Правило LEGB приме няется только к кратким, неполным именам. Ниже приводятся при нятые правила: Простые переменные Использование краткой формы имени, например X, означает, что будет произведен поиск этого имени в текущих областях видимости (следуя правилу LEGB). Полные имена Имя X.Y означает, что будет произведен поиск имени X в текущих об ластях видимости, а затем будет выполнен поиск атрибута Y в объек те X (не в областях видимости). 512 Глава 19. Основы программирования модулей Полные пути Имя X.Y.Z означает, что будет произведен поиск имени Y в объекте X, а затем поиск имени Z в объекте X.Y. Общий случай Дополнение имен применимо ко всем объектам, имеющим атрибу ты: модулям, классам, расширениям типов на языке C и т. д. В шестой части книги мы увидим, что дополнение имен для классов имеет немного большее значение (здесь также имеет место то, что на зывается наследованием), но в общем случае правила, описанные здесь, применяются ко всем именам в языке Python. Импортирование и области видимости Как мы уже знаем, невозможно получить доступ к именам, определен ным в другом модуле, не импортировав его предварительно. То есть вы никогда автоматически не получите доступ к именам в другом файле, независимо от вида импортируемого модуля и вызовов функций в ва шей программе. Смысл переменной всегда определяется местоположе нием операции присваивания в программном коде, а для обращения к атрибутам всегда необходимо явно указывать объект. Например, рассмотрим два следующих простых модуля. Первый, mo+ da.py , определяет переменную X, которая является глобальной только для программного кода в этом файле, и функцию, изменяющую гло бальную переменную X в этом файле: X = 88 # Переменная X: глобальная только для этого файла def f(): global X # Изменяет переменную X в этом файле X = 99 # Имена в других модулях недоступны Второй модуль, modb.py, определяет свою собственную глобальную пе ременную X, а также импортирует и вызывает функцию из первого мо дуля: X = 11 # Переменная X: глобальная только для этого файла import moda # Получает доступ к именам в модуле moda moda.f() # Изменяет переменную moda.X, но не X в этом файле print X, moda.X При запуске этого модуля функция moda.f изменит переменную X в мо дуле moda, а не в modb. Глобальной областью видимости для функции mo da.f всегда является файл, вмещающий ее, независимо от того, из ка кого модуля она была вызвана: % python modb.py 11 99 Другими словами, операция импортирования никогда не изменяет об ласть видимости для программного кода в импортируемом файле – из Пространства имен модулей 513 импортируемого файла нельзя получить доступ к именам в импорти рующем файле. Если быть более точным: • Функциям никогда не будут доступны имена, определенные в дру гих функциях, если только они физически не вложены друг в друга. • Программному коду модуля никогда не будут доступны имена, оп ределенные в других модулях, если только они явно не были им портированы. Это поведение является частью понятия лексической области видимо+ сти – в языке Python области видимости, доступные части программ ного кода, полностью определяются физическим расположением этого программного кода в файле. Области видимости не подвержены влия ниям вызовов функций или операции импортирования. 1 Вложенные пространства имен Операция импорта не дает возможности доступа к внешним областям видимости, но она дает возможность обращаться к вложенным облас тям видимости. Используя полные пути к именам атрибутов, вполне возможно погрузиться в сколь угодно глубоко вложенные модули и по лучить доступ к их атрибутам. Например, рассмотрим следующие три файла. Файл mod3.py определяет единственное глобальное имя и атри бут операцией присваивания: X = 3 Файл mod2.py определяет свою переменную X, затем импортирует мо дуль mod3 и использует дополнение имени, чтобы получить доступ к ат рибуту импортированного модуля: X = 2 import mod3 print X, # Моя глобальная переменная X print mod3.X # Глобальная переменная X из модуля mod3 Файл mod3.py также определяет свою собственную переменную X, за тем импортирует модуль mod2 и получает значения атрибутов обоих мо дулей: X = 1 import mod2 print X, # Моя глобальная переменная X print mod2.X, # Переменная X из модуля mod2 print mod2.mod3.X # Переменная X из модуля mod3 1 Некоторые языки программирования подразумевают иной порядок дейст вий и реализуют динамические области видимости, когда области види мости в действительности могут зависеть от вызовов функций во время вы полнения программы. Это усложняет программный код, потому что смысл переменной может изменяться с течением времени. 514 Глава 19. Основы программирования модулей В действительности, когда mod1 импортирует mod2, он создает двухуров невое вложение пространств имен. Используя полный путь к имени mod2.mod3.X , он может погрузиться в модуль mod3, который вложен в им портированный модуль mod2. Суть в том, что модуль mod1 может обра щаться к переменным X во всех трех файлах и, следовательно, имеет доступ ко всем трем глобальным областям видимости: % python mod1.py 2 3 1 2 3 Однако обратное неверно: модуль mod3 не имеет доступа к именам в mod2, а модуль mod2 не имеет доступа к именам в mod1. Возможно, этот пример будет проще понять, если отвлечься от пространств имен и областей ви димости и сосредоточиться на объектах, задействованных в примере. mod2 внутри модуля mod1 – это всего лишь имя, которое ссылается на объект с атрибутами, некоторые из которых могут ссылаться на другие объекты с атрибутами (инструкция import выполняет операцию при сваивания). Для таких путей, как mod2.mod3.X, интерпретатор Python выполняет вычисления слева направо, извлекая атрибуты из объектов. Обратите внимание: в mod1 можно вставить инструкцию import mod2 и за тем использовать обращение mod2.mod3.X, но нельзя записать import mod2.mod3 – такой синтаксис используется для операции импортирова ния пакетов (каталогов), которая будет описана в следующей главе. При импортировании пакетов также создаются вложенные простран ства имен, но в этом случае инструкция import воспринимает свой ар гумент как дерево каталогов, а не как цепочку модулей. Повторная загрузка модулей Как мы уже видели, программный код модуля по умолчанию запуска ется всего один раз за все время работы программы. Чтобы принуди тельно повторно загрузить модуль и запустить программный код в нем, необходимо явно вызвать встроенную функцию reload. В этом разделе мы исследуем, как использовать возможность повторной загрузки мо дулей, чтобы сделать систему более динамичной. В двух словах: • При вызове операции импортирования (с помощью как инструкции import , так и from) программный код модуля загружается и выпол няется, только когда модуль импортируется в первый раз за время работы программы. • При последующих попытках импортировать модуль будет использо ваться объект уже загруженного модуля. Повторная загрузка и за пуск программного кода в этом случае не происходят. • Функция reload принудительно выполняет повторную загрузку уже загруженного модуля и запускает его программный код. Инст рукции присваивания, выполняемые при повторном запуске, будут изменять существующий объект модуля. Повторная загрузка модулей 515 Для чего вся эта суета вокруг повторной загрузки модулей? Функция reload позволяет изменять части программы, не останавливая всю про грамму. Благодаря функции reload эффект от изменений в программ ном коде можно наблюдать сразу же после внесения этих изменений. Повторная загрузка модулей поможет не во всех ситуациях, но она по зволит существенно сократить цикл разработки. Например, пред ставьте себе программу, предназначенную для работы с базами дан ных, которая должна при запуске соединиться с сервером – так как из менения или настройки могут проверяться немедленно после повтор ной загрузки, вам достаточно соединиться с базой данных всего один раз за весь сеанс отладки. Язык Python относится к языкам интерпретирующего типа (более или менее), поэтому в нем отсутствуют этапы компиляции/компоновки, необходимые, чтобы запустить программу, например, на языке C: мо дули загружаются динамически уже запущенной программой. Воз можность повторной загрузки обеспечивает повышение производи тельности труда, позволяя вам изменять части работающей програм мы без ее остановки. Обратите внимание, что в настоящее время функ ция reload может обслуживать только модули, написанные на языке Python, – скомпилированные модули расширений, написанные на та ких языках, как C, тоже могут динамически загружаться во время ра боты программы, но их нельзя загрузить повторно. Основы использования функции reload В отличие от инструкций import и from: • reload – это не инструкция, а встроенная функция. • Функции reload передается существующий объект модуля, а не имя. Функция reload ожидает получить объект, поэтому к моменту ее вызо ва модуль уже должен быть успешно импортирован (если операция им порта оказалась неудачной изза синтаксических или какихлибо дру гих ошибок, вам может потребоваться повторить ее, прежде чем можно будет повторно загрузить модуль). Кроме того, синтаксис инструкции import и функции reload отличается: аргумент должен передаваться функции reload в круглых скобках, а инструкции import – без них. По вторная загрузка модуля выполняется примерно следующим образом: import module # Первоначальное импортирование ...используются атрибуты модуля... ... # Теперь выполняются изменения в файле модуля reload(module) # Загрузить обновленный модуль ...используются атрибуты модуля... Это типичный случай, когда вы импортируете модуль, затем изменяе те исходный программный код в текстовом редакторе, а потом повтор но загружаете его. Когда вы вызываете функцию reload, интерпрета тор повторно читает файл с исходными текстами и выполняет инст 516 Глава 19. Основы программирования модулей рукции, находящиеся на верхнем уровне. Пожалуй, самое важное, что следует знать о функции reload, – это то, что она изменяет непосредст+ венно сам объект модуля – она не удаляет и не создает его повторно. Вследствие этого все ссылки на объект модуля, имеющиеся в програм ме, автоматически будут учитывать изменения, произошедшие в ре зультате повторной загрузки. А теперь подробнее о том, как происхо дит повторная загрузка: • Функция reload запускает новый программный код в файле моду! ля в текущем пространстве имен модуля. При повторном выполне нии программный код перезаписывает существующее пространство имен вместо того, чтобы удалять его и создавать вновь. • Инструкции присваивания на верхнем уровне файла замещают имена новыми значениями. Например, повторный запуск инструк ции def приводит к замещению предыдущей версии функции в про странстве имен модуля, выполняя повторную операцию присваива ния имени функции. • Повторная загрузка оказывает воздействие на всех клиентов, ис! пользовавших инструкцию import для получения доступа к моду! лю. Клиенты, использовавшие инструкцию import, получают дос туп к атрибутам модуля, указывая полные их имена, поэтому после повторной загрузки они будут получать новые значения атрибутов. • Повторная загрузка будет воздействовать только на тех клиентов, которые будут использовать инструкцию from в будущем. Клиенты, которые использовали инструкцию from для получения доступа к ат рибутам в прошлом, не заметят изменений, произошедших в ре зультате повторной загрузки, – они попрежнему будут ссылаться на старые объекты, полученные до выполнения перезагрузки. Пример использования reload Ниже приводится более конкретный пример использования функции reload . В следующем примере мы изменяем и повторно загружаем файл модуля без остановки интерактивного сеанса работы с интерпре татором Python. Повторная загрузка может использоваться в различ ных других случаях (смотрите врезку «Придется держать в уме: по вторная загрузка модулей»), но мы рассмотрим лишь самый простой пример. Во первых, в текстовом редакторе создайте файл модуля с име нем changer.py и добавьте в него следующее содержимое: message = "First version" def printer(): print message Этот модуль создает и экспортирует два имени – одно связано со стро кой, а другое является функцией. Теперь запустите интерпретатор Py thon, импортируйте модуль и вызовите функцию, которую он экспор тирует. Функция выведет значение глобальной переменной message: Повторная загрузка модулей 517 % python >>> import changer >>> changer.printer() First version Придется держать в уме: повторная загрузка модулей Помимо возможности перезагружать (и, соответственно, переза пускать) модули в интерактивной оболочке операция повторной загрузки может также использоваться в крупных системах, осо бенно когда стоимость перезапуска всего приложения слишком высока. Например, первыми кандидатами на использование воз можности динамической перезагрузки модулей являются систе мы, которые на запуске соединяются с серверами сети. Эта возможность также может использоваться в приложениях с графическим интерфейсом (чтобы изменять действие обработ чиков событий в графических элементах управления, не закры вая окна графического интерфейса) и при использовании Python в качестве встроенного языка в программах, написанных на C или C++ (вмещающая программа может вызывать повторную за грузку программного кода на языке Python без остановки всего приложения). За более подробным описанием повторной загруз ки обработчиков событий в графическом интерфейсе и встроен ном программном коде на языке Python обращайтесь к книге «Programming Python». Как правило, повторная загрузка позволяет программам реали зовать высокодинамичные интерфейсы. Например, Python часто используется как язык для настройки больших систем – поль зователи могут настраивать программные продукты, изменяя программный код на языке Python без необходимости переком пилировать весь продукт (и даже не имея исходных текстов это го продукта). В таких условиях программный код на языке Py thon уже сам по себе добавляет динамичности. Тем не менее, чтобы обеспечить еще более высокую динамич ность, такие системы могут автоматически выполнять повтор ную загрузку настроечного кода на языке Python с заданной пе риодичностью. В этом случае изменения, внесенные пользовате лями, автоматически вступают в силу прямо во время работы системы – нет никакой необходимости останавливать и переза пускать ее всякий раз, когда изменяется программный код на языке Python. Не все системы реализуют такой подход, но для тех из них, которые обеспечивают такую возможность, повтор ная перезагрузка модулей является простым и удобным средст вом выполнения настроек. |