Лутц М. - Изучаем Python (1077325), страница 114
Текст из файла (страница 114)
3. Каждый каталог, перечисленный в инструкции тарогт или тгоа, должен содержать файл !л!г .ру. Другие каталоги, включая каталог, содержащий самый первый компонент пути к пакету, не требуют наличия этого файла. 4. Инструкция таро г! должна использоваться вместо инструкции г гол, только если вам необходимо обеспечить доступ к одному и тому же имени более чем в одном каталоге. Благодаря инструкции тарогт употребление полного пути обеспечивает уникальность ссылок, тогда как инструкция Ггоа допускает наличие только одной версии любого имени.
Дополнительные возможности модулей Эта глава завершает пятую часть книги, представляя коллекцию более сложных тем, имеющих отношение к модулям, — синтаксис относительного импорта, сокрытие данных, модуль 1стсге, переменная саве, изменение списка зуз. раГЬ и т. д. и, кроме того, содержит перечень наиболее типичных ошибок и упражнения, завершающие эту часть книги. Как и функции, модули наиболее эффективны, когда должным образом определены их интерфейсы, поэтому в данной главе представлен краткий обзор концепций проектирования модулей, некоторые из которых мы исследовали в предыдущих главах.
Несмотря на слово «дополнительные» в заглавии этой главы, некоторые из обсуждаемых здесь возможностей (такие, как приемы работы с переменной паве ) используются достаточно широко, поэтому обязательно ознакомьтесь с ними, прежде чем переходить к классам в следующей части книги. Сокрытие данных в модулях Как мы уже видели, модули в языке РуСЬоп экспортируют все имена, которым были присвоены значения на верхнем уровне файлов.
В языке нет никаких объявлений, которые позволили бы сделать одни имена видимыми, а другие — невидимыми за пределами модуля. Фактически нет никакого способа предотвратить возможность изменения имен в модуле извне, если в этом появится необходимость. Сокрытие данных модуля в языке РуФЬоп регулируется соглашениями, а не синтаксическими конструкциями.
Если задаться целью повредить модуль, изменяя имена в нем, вам ничто не сможет помешать, но, к счастью, я еще не встречал программистов, кто стремился бы это сделать. Некоторые пуристы возражают против такого либерального отношения к сокрытию данных, утверждая в связи с этим, что в языке Глава 21. Дополнительные возможности модулей Ру$Ьоп отсутствует возможность инкапсуляции. Инкапсуляция в языке Ру$йоп скорее относится к организации пакетов, чем к возможности накладывать ограничения.
Минимизация повреждений, причиняемых инструкцией Фгоп) *: Х и аП Как особый случай, существует возможность начинать имена переменных с одного символа подчеркивания (например, Х), чтобы предотвратить их перезаписыванне, когда клиент выполняет импортирование модуля инструкцией ( гов *, Этот прием на самом деле предназначен только для минимизации загрязнения пространства имен — так как инструкция Егоэ * копирует все имена, импортирующий модуль может получить больше, чем предполагал (включая имена, которые перезапишут имена импортирующего модуля). Символы подчеркивания не являются объявлением»частных» данных: вы по-прежнему можете видеть эти имена и изменять их с помощью других форм импортирования, таких как инструкция таро гт.
Альтернативный способ достижения эффекта сокрытия данных, напоминающий соглашение об именовании Х, заключается в присвоении на верхнем уровне модуля переменной а11 списка строк с именами переменных. Например: а11 = ("Еггог", "епсоое", "Сасове" 1 Ф Экспортируются тспькс эти имена При использовании этого приема инструкция г гол * будет копировать только имена, перечисленные в списке а11 . В действительности это соглашение, обратное соглашению Х: переменная а11 идентифицирует имена, доступные для копирования, тогда как соглашение Х идентифицирует имена, недоступные для копирования.
Интерпретатор Ру1)топ сначала отыскивает список а11 в модуле, и если он отсутствует, инструкция Е гоа * копирует все имена, которые не начинаются с единственного символа подчеркивания. Подобно соглашению Х, список а11 имеет смысл только для инструкции Г тою ° и не является объявлением частных данных. Программисты могут использовать при реализации модулей любой из этих приемов, которые хорошо работают с инструкцией Етою *. (Смотрите также обсуждение списков а11 в файлах пакетов (л(т .ру в главе 20 — там эти списки объявляют субмодули, которые могут быть загружены инструкцией тгоэ *.) Включение будущих возможностей языка В языке периодически появляются изменения, которые могут повлиять на работоспособность существующего программного кода.
Сначала они появляются в виде расширений, которые по умолчанию отключены. Чтобы включить такие расширения, используется инструкция импорта специального вида: 535 Смешанные режимы использования: пате и тат Ггов гцгцге тврогг имя функцио~ал~ной особенности Например, в предыдущем издании этой книги мы использовали зту форму инструкции для демонстрации функций-генераторов, в которых используется ключевое слово, еще недоступное по умолчанию в то время (в качестве имя функциональной особенности указывалось имя депегаСоге).
Мы уже использовали эту инструкцию для включения операции истинного деления чисел в главе б и будем использовать ее и в этой главе для включения возможности абсолютного импорта, а также в седьмой части книги — для демонстрации менеджеров контекста. Все эти изменения могут отрицательно сказаться на работоспособности существующего программного кода, и поэтому они так постепенно вво- дятся в язык — сначала в виде дополнительных возможностей, вклю- чаемых с помощью этой специальной формы инструкции импорта.
Смешанные режимы использования: пате и талип Ниже демонстрируется специальный прием, позволяющий импортировать файлы как модули и запускать их как самостоятельные программы, Каждый модуль обладает встроенным атрибутом паве, который устанавливается интерпретатором следующим образом: ° Если файл запускается как главный файл программы, атрибуту паве на запуске присваивается значение " вазе ° Если файл импортируется, атрибуту паве присваивается имя модуля, под которым он будет известен клиенту. Благодаря этому модуль может проверить собственный атрибут паве и определить, был он запущен как самостоятельная программа или импортировав другим модулем.
Например, предположим, что мы создаем файл модуля с именем гиппзе.ру, который экспортирует единственную функцию с именем вевсег: Оег гевгег(> ргьи '?г в Спывгвав зп неачеп... Ф тол~ко когда запускается, Ф а не импортируется зт паве == ваго гевгег() Этот модуль определяет функцию для клиентов и может импортиро- ваться как обычный модуль: Эта инструкция вообще должна появляться в самом начале файла модуля (возможно, сразу же вслед за строкой документирования), потому что она включает специальный режим компиляции программного кода для каждого отдельно взятого модуля.
Возможно также выполнить эту инструкцию в интерактивной оболочке, что позволит поэкспериментировать с грядущими изменениями в языке; включенная особенность будет после этого доступна в течение всего интерактивного сеанса. 536 Глава 21. Дополнительные возможности модулей % рутпоп »> тэрогт голее »> гопае.театег() 11'я Спг)ятпая тп неаоеп.. Но в самом конце модуля имеется программный код, который вызывает функцию, когда этот файл запускается как самостоятельная программа: % рутлоп гопэе.ру !т'я Слгтятеая тп Неахеп...
Пожалуй, чаще всего проверка атрибута паве выполняется в программном коде для самопроверки модуля. Проще говоря, вы можете добавить в конец модуля программный код, который будет выполнять проверку экспортируемых элементов внутри самого модуля, заключив этот код в условную инструкцию, проверяющую атрибут паве . При таком подходе вы можете использовать файл в других модулях, импортируя его, и тестировать логику работы, запуская его из командной строки или каким-либо другим способом. На практике программный код самопроверки в конце файла, заключенный в условную инструкцию, проверяющую атрибут паве, является, пожалуй, самым распространенным и удобным способом модульного тестирования в языке Ру$Ьоп.
(В главе 29 обсуждаются другие часто используемые способы тестирования программного кода на языке РуФ)топ — как будет показано, в стандартной библиотеке существуют модули ип!ыеяс и Состеят, которые реализуют более совершенные средства тестирования.) Прием, основанный на проверке атрибута паве, также часто используется при создании файлов, которые могут использоваться и как утилиты командной строки, и как библиотеки инструментов.
Например, предположим, что вы пишете на языке Ру$]топ сценарий поиска файлов. Код принесет больше пользы, если реализовать его в виде функций и добавить проверку атрибута паве для организации вызова этих функции, когда файл запускается как самостоятельная программа. При таком подходе сценарий может повторно использоваться в составе других программ.
Тестирование модулей с помощью пате Мы уже видели в этой книге один хороший пример, применительно к которому проверка атрибута паве могла бы быть полезной. В разделе, рассказывающем об аргументах, в главе 16, мы написали сценарий, который находит минимальное значение среди множества предложенных аргументов: Оег этапах(теят, *агро). гея = агдяГО] Гог агд тп агдя[1 ]' тг таят(агд, гея). гея = агд Смешанные режимы использования: папзе и гпа~п ге(огп гев оег 1еввгпап(х, у). гегогп х < у оег дг(ггпап(х, у); ге(огп х > у рггп1 а!паах(1евв1яап, 4, 2, 1, 5, б, 3) Ф Код самопроверки ргшг юпвах(дг(г1оап, 4, 2, 1, 5, 6, 3) В самом конце этого сценария присутствует программный код самопроверки, благодаря которому мы можем проверить правильность работы модуля без необходимости вводить его в интерактивной оболочке всякий раз, когда нам потребуется проверить модуль.