Саммерфилд - Программирование на Python 3 (1077331), страница 47
Текст из файла (страница 47)
164, 170 Ниже приводится пример простой лямбда-функции, которая добавля- ет (или не добавляет) суффикс «в «в зависимости от того, имеет ли ар- гумент значение 1; 216 Глава 4. Управляющие структуры и функции цию. Например, если необходимо отсортировать список не по естественному порядку: номер группы, порядковый номер и название, а по порядковому номеру и названию, то мы могли бы написать маленькую функцию Се[ тдпсгеО(е): ге!о гп е[1], е[2] и передавать ее в аргументе кеу. Но создавать в программе массу крошечных функций, подобных этой, очень неудобно, поэтому часто используется альтернативный подход, основанный на применении лямбда-функций: е1езепта.асгт(кеу=1ааьса а: (е[1]. е[2])) Здесь в качестве значения аргумента Кеу используется выражение 1асЬСа е: (е[1], е[2]), которому в виде аргумента е последовательно передаются все трехэлементные кортежи из списка.
Круглые скобки, окружающие лямбда-выражение, обязательны, когда выражение является кортежем и лямбда-функция создается как аргумент другой функции. Для достижения того же эффекта можно было бы использовать операцию извлечения среза: е1ееета,аогт(оеу=1ааЬСа а: е[1гв]) Немного более сложная версия обеспечивает возможность сортировки по названию, без учета регистра символов, и порядковому номеру; е1апепта.асгт(кеу=1агаьса е: (а[2],1сиег(), е[1])) Ниже приводятся два эквивалентных способа создания функции, вычисляющей площадь треугольника по известной формуле 1 х основание х высота: Се( агеа(Ь, Ь): агеа = 1ааЬСа Ь, П; 0.5 * Ь * Ь ! гетогп 0.5 * Ь * Ь Мы можем вызвать функцию агеа(6, 5) независимо от того, была ли она создана как лямбда-функция или с помощью инструкции Се!, и результат будет один и тот же.
Другая замечательная область применения лямбда-функций — создание словарей со значениями по умолчанию. В предыдущей главе говорилось, что при обращении к такому словарю с несуществующим ключом будет создан соответствующий элемент с указанным ключом и со значением по умолчанию. Ниже приводятся несколько примеров создания таких словарей: а!поа спе стст = сс11ест!Ьпа.сетао110!ст(1аэьса. -1) ро!пт гаго 01ст = сс11ест!Ьпа.сегао1тстст(1аяьса. (О, О)) ееааада с!с! = сс11ест!Ьпа.сетао1тстст(1азьса: Гвс заваада аоа!1аь)а") При обращении к словарю з!поа опе Ьтст с несуществующим ключом будет создан новый элемент с указанным ключом и со значением -1.
Точно так же при обращении к словарю ротс! лего О!01 вновь созданный элемент получит в качестве значения кортеж (О, 0), а при обра- Собственные функции щении к словарю эевваде о!ст значением по умолчанию будет строка «Хо тпезваяе ача1!аЫе». Утверждения Что произойдет, если функция получит аргументы, имеющие ошибочные значения? Что случится, если в реализации алгоритма будет допущена ошибка и вычисления будут выполнены неправильно? Самое неприятное, что может произойти, — это то, что программа будет выполняться без каких-либо видимых проблем, но будет давать неверные результаты.
Один из способов избежать таких коварных проблем состоит в том, чтобы писать тесты, о которых кратко будет рассказано в главе 5. Другой способ состоит в том, чтобы определить предварительные условия и ожидаемый конечный результат, и сообщать об ошибке, если они не соответствуют друг другу. В идеале следует использовать как тестирование, так и метод на основе сравнения предварительных условий и ожидаемых результатов. Предварительные условия и ожидаемый результат можно задать с помощью инструкции авве гт, которая имеет следующий синтаксис: авввгт Ооо1еап ехргеввтоп, оргтопа1 ехргеввтоп Оат ргосост(*агдв): а оптииистичная гвво11 = 1 тог агц 1п агцв.
гаво11 *= агд аввегт гаво!т, "О агцоиепт" гетогп гаво11 Овт ргосост(*агдв): Ф пессимистичная авввгт а11(агдв), "О агцоавпт" гево11 = 1 тог агд 1п агдв. гаво11 ° = агц гатогп гвво11 «Пессимистичная» версия, слева, проверяет все аргументы (точнее— до первого нулевого значения) при каждом вызове. «Оптимистичная» версия, справа, проверяет результат — если хотя бы один аргумент имеет нулевое значение, то и результат будет равен О. Если выражение Ооо!еап ехргеввуоп возвращает значение Еа1ве, возбуждается исключение Аввегт(опЕггог.
Если задано необязательное выражение оргтопа1 ехргеввуоп, оно будет использовано в качестве аргумента исключения Аввегт(опЕггог, что удобно для передачи сообщений об ошибках. Однако следует отметить, что утверждения предназначены для использования разработчиками, а не конечными пользователями.
Проблемы, возникающие в процессе нормальной эксплуатации программы, такие как отсутствующие файлы или ошибочные аргументы командной строки, должны обрабатываться другими средствами, например, посредством вывода сообщений об ошибках или записи сообщений в файл журнала. Ниже приводятся две версии функции ргодосС(). Обе версии эквивалентны в том смысле, что обе они требуют, чтобы все передаваемые им аргументы имели ненулевое значение, а вызов с нулевыми значениями рассматривается как ошибка программиста. г1В Глава 4. Управляющие структуры и функции Если любую из этих версий вызвать со значением О в одном из аргументов, будет возбуждено исключение Аввегт!ООЕггог и в поток стандартного вывода сообщений об ошибках (вув.вЫегг — обычно консоль) будет выведено следующее: тгасеоаск (пов! гесепт са11 1азт): Е!1е "ргодгав ру", 1!пе 456, !и <посо1е> х = ргосост(1, 2, О, 4, 81 Р!1е "ргодгаэ.ру", 1!пе 452, !и ргооос! аваег! гево11, "О агдовеп!" Аззегт!опЕггог: О агдопепт Интерпретатор автоматически выведет диагностическую информацию с именем файла, именем функции и номером строки, а также текст сообщения, указанного нами.
Но как быть с инструкциями аввегс, после того как программа будет готова к выпуску в виде окончательной версии (при этом она, безусловно, успешно проходит все тесты и не нарушает ни одного утверждения) г Мы можем сообщить интерпретатору о том, что больше не требуется выполнять инструкции азвегт, то есть их нужно отбрасывать во время выполнения программы. Для этого программа должна запускаться с ключом командной строки -О, например ру! поп -0 р год гав. ру. Другой способ добиться этого состоит в том, чтобы установить переменную окружения РУТНОНОРТ1Н11Е в значение О.' Если наши пользователи не пользуются строками документирования (обычно им этого и не требуется), мы можем использовать ключ -00, который эффективно удаляет как инструкции авве г!, так и строки документирования: обратите внимание, что для установки такого поведения нет переменной окружения.
Некоторые разработчики используют упрощенный подход: они создают копии программ, где все инструкции аввег! закомментированы, и в случае прохождения всех тестов они выпускают версию программы без инструкций авве г!. Пример: та1се Ыт! я|се!европ.ру В этом разделе мы объединим некоторые приемы, описанные в этой главе, и продемонстрируем их в контексте законченной программы. Очень маленькие веб-сайты часто создаются и обслуживаются вручную. Один из способов облегчить эту работу состоит в том, чтобы написать программу, которая будет генерировать заготовки файлов НТМ1., которые позднее будут наполняться содержимым. Программа та)ге Ыт1 ейе(е!оп ру выполняется в интерактивном режиме, она запрашивает у пользователя различные сведения и затем создает заготовку файла НТМЬ.
Функция ва!п() содержит цикл, позволяющий создавать одну заготовку за другой, и сохраняет общую информацию (на- Это буква еОэ, а ве цифра О. — Прил. перев. 219 Пример: газке Н!гп( еке(е!оп.ру пример, информацию об авторских правах), что избавляет пользовате- лей от необходимости вводить ее снова и снова. Ниже приводится при- мер типичного сеанса работы с программой: вахе П!в1 еке1е!оп.ру МеКе Н?МЕ ЕКе)е!оп Сгеа!е апо!пег (у/и)» [у]; МаКе НТМ[ Бке1егоп Еп!ег уоиг паве (Гог сорумцм) [Него!О Р1пгег]: Еп!ег соруг!цо! Уеег [2009]: Епгег Г!1епеве: Сапсе11еи Сгеаге апогпег (у/и)? [у]: и Обратите внимание, что при создании второй заготовки имя и год получили значения по умолчанию, введенные ранее, поэтому пользователю не пришлось вводить их вторично.
Но для имени файла значение по умолчанию отсутствует, поэтому, когда имя файла не было указано, процедура создания заготовки была прервана. Теперь, когда мы увидели, как пользоваться программой, мы готовы приступить к изучению программного кода. Программа начинается двумя инструкциями импорта: юрог! са!ег!ве !врог! хв1.еах.пахи!11е Модуль Сз!е!1ве предоставляет ряд простых функций для создания объектов Сз!е!!ве. Са!е и цз!е1!ве.1!ве. Модуль хв1.
зах. пахи!!1з содержит удобную функцию хв1. зах, пахи!11з, езсаре(), которая принимает строку и возвращает эквивалентную ей строку, в которой специальные символы языка разметки НТМЬ («((», «<» и «>») замещаются их эквивалентами («((авр; », «611; » и «201; »). Далее определяются три глобальные строки, которые используются в качестве шаблонов. Епгег Еп!ег Епгег Еп!ег Еп!ег Еп!ег Еп!ег Еп!ег Епгег Еп!ег яеуео уоиг паве (Гог соруг!9П!): Наго10 Р!и!ег соруг!цо! Уеаг [2008]. 2009 Г!1епеве: сагеег-еупореге !!!1е: Сагеег Яупоре!е оеесг1р!1оп (ор!гопа1): зупоре!з ог !Не сагеег ог наго1о Р1п!ег а кеувого (орг!опе1): р1еуи»дн! а кеувого (ор!шпа1): ас!ог е кеу«ого (ор!1опа1): ас!!Уге! е кеувого (ор!!опе1): гпе е!У1еэпее! г!1епаве (ор!!опа1): е!У1е БКе1е!оп сегеег-еупоре!е.о!в1 гго Глава 4.
Управляющие структуры и функции сОРун10нт темРЕАте = "соруг1цпс (с) (0) (т). А11 г1цьсз гезегхеб." БТУЕЕЗНЕЕТ ТЕМРЕАТЕ = ('<11пК ге1="зту1езоееС" Суре="Сехт/сзз" 'веб1е="а11" Пгет="(0)" />Хп') НТМЕ ТЕИР1АТЕ = """<?ха1 негыоп="1.0"?> <!00стуРе ьса1 РОВпс "-//нзс//От0 хнтмс 1.0 Ясг1сс//еи" Х "псср://апа.из.огц/тн/хьса11/ОтО/хьса1т-зсысс.бсб"> <ПСМ1 хв1пзы'ПССР://ааа. вЗ. огц/1999/хотв1" 1апц="еп" ха1; 1апц="еп"> <Пееб> <стс1е>(с1с1е)</11с1е> <!-- (сосут!цпс) --> <веса паве="Оезсг1рссоп" сопсепс="(безсгсрстоп)" /> <вета певек'Кеуаогбз" соптепты'(Кеуногбз)" /> <весе ецо1у="сопсепс-суре" сопсепсы'сехс/пса1; спвгзес=ос(-8" /> (зсу)езпеес)Х </Пеаб> <Ьобу> </Ьобу> </ЬСМ1> о Эти строки будут использоваться как шаблоны для вызоМетод зсг.