Саммерфилд - Программирование на Python 3 (1077331), страница 52
Текст из файла (страница 52)
209 скольку в настоящее время нас интересуют модули, а не функции, мы продемонстрируем только программный код функции 18 Ьа1апсеб(), хотя функцию в!щр11йу() приведем полностью, вместе со строкой документирования. Ниже приводится функция вгщр1гбу( ), разбитая на две части: оет юшр1гту(!ехт, иь1!еврасе=втгтпд.иь(саврасе, бе1ете=""): г"""Возвращает текст, из которого удалены лишние пробелы. Параиетр ил!саврасе - зто строка символов, каждый из которых считается символом пробела. Если параметр Ое1ете не пустой, он должен содержать строку, и тогда все символы. входящие в состав строки Ое1ете, будут удалены из строки результата.
»> в1шр1!Ту(" то!в апоша тле!1! !оо") 'т)ив апо тпа! !оо' »> в!ар!!Ту(" иавГнпд!оп 0.0.1п") 'щавпгпдтоп О.С.' »> в(шр1гту(" шапа!од!оп О.с.'~п", бе1ете=",;:.") 'Хавпглд!Ьп ОС' »> в1шр)!Ту(" Отвещчоие)ес ", Ое1ете="аегоо") 'Овшчи1С' Модули и пакеты 239 Вслед за строкой с инструкцией бе( следует строка доку- «Сырые» ментирования функции, первая строка которой в соот- отроки ветствии с соглашениями является коротким одностроч- стр. 85 ным описанием; за ней следуют пустая строка, более подробное описание и затем несколько примеров, записанных так, как если бы они выполнялись в интерактивной оболочке.
Поскольку в строке документирования присутствуют кавычки, мы должны либо экранировать их символом обратного слеша, либо, как в данном случае, использовать «сырую» строку в тройных кавычках. гезо11 = [] иогб = "" тог слаг 1п техт: тт сааг тп бе1ете. сопттпое е1тт олаг тп ил11озраое: тт иогб: гаво1т.аррапб(иогб) иогб = "" е1ве: хогб »= слаг тт иогб: гаво1(.аррепб(иогб) гатогп " ".)отп(гезо11) Список гево11 используется для хранения «сло⻠— строк, не имеющих пробельных или удаляемых символов. Внутри функции выполняются итерации по символам в параметре техт, с пропуском удаляемых символов.
Если встречается пробельный символ и в переменной иогб содержится хотя бы один символ, полученное слово добавляется в список гезо11, после чего в переменную иогб записывается пустая строка; в противном случае пробельный символ пропускается. Любые другие символы добавляются к создаваемому слову. В конце функция возвращает единственную строку, содержащую все слова из списка гезо11, разделенные пробелом. Функция тз Ьа1апоеб() следует тому же шаблону: за строкой с инструкцией бег находится строка документирования с коротким однострочным описанием, пустой строкой„полным описанием и несколькими примерами, вслед за которой идет сам программный код.
Ниже приводится только программный код функции, без строки документирования: бе( 1з ьа1апсаб(техт, ьгаокатвы'()[]()<>"): сооптв = () )атт тпг г(длт = () гог 1атт, г1дпт [п в1р(ьгаохетв[::2], ьгаохетв[т:.2]): аввегт 1атт .'= г(длт, "тпе Ьгаокет слагастегз аозт б1(тег" сооптв[1агт] = 0 240 Глава 5. Модули 1епг Гог г1дж[г1ды] = 1епг Гог с ап гехо. 11 с ап сооп1а: сорога[с] += 1 еШ с «и )еГ1 Гог гадПГ: 1ег1 = 1егг гог г[дпг[с] аг соопга[1егг] == 0: гегогп ра!ае соопга[1егг] -= 1 гегогп по1 апу(сорога.ча1оеа()) Функция создает два словаря.
Ключами словаря сапога являются символыоткрывающихскобок(«(», «[», «(» и «<»),азначениями — целые числа. Ключами словаря 1е[1 гог г[дпг являются символы закрывающих скобок («)», «)», «)» и «>»), а значениями — соответствующие им символы открывающих скобок.
Сразу после создания словарей функция начинает выполнять итерации по символам в параметре гехг. Всякий раз, когда встречается символ открывающей скобки, соответствующее ему значение в словаре соопг увеличивается на 1. Точно так же, когда встречается символ закрывающей скобки, функция определяет соответствующий ему символ открывающей скобки. Если счетчик для этого символа равен О, это означает, что была встречена лишняя закрывающая скобка, поэтому можно сразу же возвращать Га1зе; в противном случае счетчик уменьшается на 1.
По окончании просмотра текста, если все открывающие скобки имеют парные им закрывающие скобки, все счетчики должны быть равны О, поэтому, если хотя бы один счетчик не равен О, функция возвращает Га1ае; в противном случае она возвращает Тгсе. До этого момента рассматриваемый модуль ничем не отличался от любого другого файла с расширением .Ру. Если бы файл Техг[ТО].ру был программой, вполне возможно, что в нем присутствовали бы и другие функции, а в конце стоял бы единственный вызов одной из этих функций, запускающий обработку.
Но так как это модуль, который предназначен для того, чтобы его импортировали, одних определений функций вполне достаточно. Теперь любая программа или модуль смогут импортировать модуль Техго111 и использовать его: юрогп ТехГОГ11 1ехг = а рога1ыд сопопогоа " гехг = ТехГОЫ1.ааар1>Гу(Сех1) П 1ех1 == 'а рогг1«пд сопопсгоа' Если нам потребуется сделать модуль Техг])гг1 доступным определенной программе, нам достаточно будет поместить файл Техг[ТО[ру в один каталог с программой.
Сделать файл ТехЖгйру доступным для всех наших программ можно несколькими способами. Первый состоит в том, чтобы поместить модуль в подкаталог айе-рас)«ауеа, находящийся в дереве каталогов, куда был установлен Ру(Ьоп (в системе Ъ[пдочгв это обычно каталог С:ч,Руа)«опЗОч,ИЬ|а1 Ге-расйауеа, но в Мас 03 Х и других Модули и пакеты версиях Т))к)1Х путь к этому каталогу будет иным). Данный каталог находится в пути поиска Ру1)топ, поэтому интерпретатор всегда будет отыскивать любые модули, находящиеся здесь. Второй способ заключается в создании каталога, специально предназначенного для наших собственных модулей, которые мы предполагаем использовать в наших программах, и добавлении пути к этому каталогу в переменную окружения РтТНОИРЯТН.
Третий способ состоит в том, чтобы поместить модуль в локальный подкаталог в(ге-расйадев — каталог %АРРВАТА%/ Ругйоп/Ругйоп30/з(ге-расйауез в ЪУ1пдотвв, и -/.1оса1/11Ь/ругйол3.0/з(терасйауез в ()Х1Х (включая Мас ОВ Х), который находится в пути поиска Ру()топ. Второй и третий подходы предпочтительнее, так как в этих двух случаях ваш программный код будет храниться отдельно от официальной версии Ру1)топ. Иметь модуль ТехтНЫ1 само по себе уже неплохо, но если в конечном счете предполагается использовать его во множестве программ, то наверняка хотелось бы пребывать в уверенности, что он работает именно так, как заявлено.
Один из самых простых способов состоит в том, чтобы выполнить примеры, которые приводятся в строках документирования, и убедиться, что они дают ожидаемые результаты. Сделать это можно, добавив всего три строки в конец файла модуля: тт паве == " эа1п юоогт оостевт оостевт тевтвоо() Всякий раз, когда выполняется импортирование модуля, интерпретатор создает для него переменную с именем паве и сохраняет имя модуля в этой переменной.
Имя модуля — это просто имя файла .Ру, только без расширения. Поэтому в данном случае, когда модуль будет импортироваться, переменная паве получит значение "Техт()111" и условие в инструкции 11 не будет соответствовать Тгсе, то есть две последние строки выполняться не будут.
Это означает, что последние три строки ничего не меняют, когда модуль импортируется. Всякий раз, когда файл с расширением .ру запускается как программа, интерпретатор Ру1)топ создает в программе переменную с именем паве и записывает в нее строку" эатп ". То есть, если мы запустим файл ТехгШ11 ру как программу, интерпретатор запишет в переменную паве строку" аатп ", условие в инструкции т1 вернет Тгое и две последние строки будут выполнены.
Функция достезт. тевтэоН() с помощью механизма интроспекции Ру1Ьоп выявляет все функции в модуле и их строки документирования, после чего пытается выполнить все фрагменты программного кода, которые приводятся в строках документирования. При запуске модуля таким способом вывод на экране появится только при наличии ошибок. Сначала это может привести в замешательство, так как создается впечатление, будто вообще ничего не происходит; но если интерпретатору 242 Глава 5. Модули передать ключ командной строки -у, на экране может появиться примерно следующее: Тгуьпбл 4в ьа1впсео("(Ру(поп (1в (по1 ( 1!зр)))) ) Ехрес11пр: Тгое ох Тгу!пбп з1ар111у(" огзеахоае1ео ", ое1есе="ае!оо") Ехрес11пр: овача10 ох 4 41еав раввео а11 1ев1в.
3 1ев1в 1п аа!п 5 1езсв )п ав!и .1в Ьа1апсео 3 1езгв 1п ,аа!п .впоггеп 4 1евсв 1п ав1П .3!ар11(у 15 1евсв 1п 4 г1ааз. 15 раввео впо О Га!1ео. Тезг развез. Мы использовали многоточия, чтобы показать, что было опущено множество строк. Если в модуле имеются функции (или классы, или методы), не имеющие тестов, при запуске интерпретатора с ключом -ч они будут перечислены. Обратите внимание, что модуль 0ос(ев1 обнаружил тесты как в строке документирования модуля, так и в строках документирования функций.
Примеры в строках документирования, которые могут выполняться как тесты, называют докглестами (4(ос(ев(в). Обратите внимание, что при написании доктестов мы вызываем функцию в!ар1!Гу(), не используя полное квалифицированное имя (поскольку доктесты находятся непосредственно в самом модуле). За пределами модуля, после выполнения инструкции ппрог1 Тех101!1, мы должны использовать квалифицированные имена, например, Тех(01!1. !в Ьа1апсес(). В следующем подразделе мы увидим, как реализовать более полноценные тесты — в частности, проверку случаев, когда ожидаются отказы,— например, когда неверные входные данные должны приводить к воз-, буждению исключения. Мы также рассмотрим некоторые другие проблемы, связанные с созданием модулей, включая инициализацию модуля, учет различий между платформами и обеспечение возможности импортировать программами или модулями, при использовании синтаксиса (гоа аоси)е 1арог1 *, только тех объектов, которые мы хотим сделать общедоступными.
Модули и пакеты 243 Модуль СЬагбгЫ Модуль Слагйгтс хранит в памяти сетку символов. Он предоставляет функции, позволяющие «рисовать» в сетке линии, прямоугольники и текст, а также функции отображения сетки в консоли. Ниже приво- дятся доктесты из строки документирования модуля: »> гев!ае(!4, 50) »> аоз гестапд!е(0, О, *де! в!ае()) »> аоо чегт1са1 1>ое(5, 1О, !3) »> асс чегт!са1 1!пе(2, 9, 12, "!") »> аоо логваоота1 1!ее(3, 10, 20, "+") »> асс гестаод1е(0, О, 5, 5, "%") »> аоо гестао91е(5, 7, !2, 40, "ю", тгое) »> аоо гестао91е(7, 9, !О, 38, " ") »> аоо техт(8, 10, "то>в !в тле саагдг!о аооо1е") »> аоо техт( к 32, "Р1еаваотчт1 1е ', "э" ) »> аоо гестапо)е(8, 42, «, 48, г ы=тгое) »> гепсег(га1ве) Функция Спагбг16, асс гестал91е() принимает четыре обязательных аргумента: номер строки и номер столбца верхнего левого угла, а также номер строки и номер столбца правого нижнего угла. В пятом необязательном аргументе можно определить символ, который будет использоваться для рисования сторон прямоугольника, а в шестом аргументе типа Воо)еап можно указать, следует ли выполнять заливку прямоугольника (тем же самым символом, который используется для рисования сторон).
В первом вызове третий и четвертый аргументы передаются путем распаковывания двухэлементного кортежа (ширина и высота), который возвращает функция Спагбг(0. де! 312е(). %%%%%* % % % % % % ««««+«++«« %%%%% аааааааааааааивааоааааааваааааааа аавааввваавааваааоаааааававвааааа ао ао ва то>в тв тле слаг6гто аоои1е ао *! 44 44 * ' ! ыавааааааоаваааааааааааааоивааааа ° ' ( ааавааааааааоаававааааваааввааааа ! Рзаэд«гея«эвами ЭР1еаваотю11еэ Ээазаааасчфааза По умолчанию, прежде чем вывести содержимое сетки, функция Спа гСг(д. гепдег() очищает экран, но чтобы предотвратить это, ей можно передать значение Еа1ве, что и было сделано в данном случае. Ниже приводится изображение сетки, полученной в результате выполнения доктестов: 244 Глава 5, Модули Модуль Спагйг)О начинается точно так же, как и модуль Тех!0!11— со строки «з)геЬапя», с упоминания об авторских правах и лицензионном соглашении.