Саммерфилд - Программирование на Python 3 (1077331), страница 88
Текст из файла (страница 88)
Кроме того, не забывайте, что в файлах переменной длины последний блок может оказаться коротким. Для обозначения непечатаемых символов используйте точку, как показано в примере. Программу можно уместить менее чем в 70 строк, распределенных на две функции. Пример решения приводится в файле хс[иглр.ру. Усовершенствованные приемы программирования В этой главе мы рассмотрим широкий диапазон различных приемов программирования и представим множество дополнительных, усовершенствованных синтаксических конструкций, поддерживаемых языком Рубанов.
Некоторые сведения, приводимые в этой главе, отличаются высокой сложностью, но имейте в виду, что большая часть дополнительных приемов используется нечасто и при первом прочтении вы можете лишь ознакомиться с ними, чтобы получить о них общее представление, и перечитать материал внимательнее, когда в этом возникнет необходимость. В первом разделе главы более подробно рассматриваются особенности процедурного программирования на языке РуФЬоп.
Раздел начинается с демонстрации решения уже описанных ранее задач новым способом и затем возвращается к теме генераторов, которая кратко рассматривалась в главе 6. Затем в этом разделе рассматриваются приемы динамического программирования — загрузка модулей по имени во время выполнения и выполнение произвольного программного кода. После этого изложение возвращается к теме локальных (вложенных) функций, которая расширена описанием использования ключевого слова соп1оса1 и рекурсивных функций. Ранее мы видели, как можно использовать предопределенные декораторы языка РуФоп, а в этом разделе мы узнаем, как создавать собственные декораторы. Завершается раздел обсуждением аннотаций функций.
Во втором разделе содержатся новые сведения об объектно-ориентированном программировании. Он начинается с представления механизма слотов ( э1о(э ), предназначенного для уменьшения объема памя- Улучшенные приемы процедурного программирования ти, занимаемой каждым объектом. Затем он демонстрирует, как организовать доступ к атрибутам без использования свойств. В этом разделе также будут представлены функторы (объекты, которые могут вызываться подобно функциям) и менеджеры контекста — они используются совместно с ключевым словом н11П и во многих случаях (например, при работе с файлами) могут использоваться вместо конструкций ггу ...
ехСЕР1 ... г1ла11у, замещая их более простыми конструкциями ггу ... ехсерг. В этом разделе также будет показано, как создавать свои собственные менеджеры контекста, и будут представлены дополнительные улучшенные особенности объектно-ориентированного программирования, включая декораторы классов, абстрактные базовые классы, множественное наследование и метаклассы. В третьем разделе вводится несколько фундаментальных понятий функционального программирования и представлены некоторые полезные функции из модулей гцпсгоо1в, 11еггоо1в и оре гаго г.
В этом разделе также будет показано, как использовать возможность частичной подготовки функций для упрощения программного кода. Предыдущие главы предоставили нам «комплект стандартных инструментов языка РУФЬоп». Эта глава берет все, что мы уже рассматривали, и превращает в «комплект усовершенствованных инструментов», в котором присутствуют все прежние инструменты (приемы программирования н синтаксические конструкции) плюс множество новых, которые могут сделать программирование проще, легче и эффективнее. Некоторые инструменты являются взаимозаменяемыми, например, некоторые задачи можно решать с помощью декораторов классов или метаклассов„ тогда как другие, такие как дескрипторы, при разных способах использования дают различные результаты.
Некоторые описываемые здесь инструменты, такие как менеджеры контекста, мы будем использовать постоянно, другие — время от времени, только в определенных ситуациях, когда они способны предложить лучшее решение. Улучшенные приемы процедурного программирования Большая часть этого раздела посвящена дополнительным возможностям„касающимся процедурного программирования и функций, но самый первый подраздел в этом отношении стоит особняком, так как в нем представлены полезные приемы программирования, основанные на уже имеющихся у нас знаниях, без введения новых синтаксических конструкций.
Ветвление с использованием словарей Как уже отмечалось ранее, функции — это объекты, как и все остальное в языке РуФ)гоп, а имена функций — это ссылки на объекты, кото- 39б Глава 8. Усовершенствованные приемы программирования рые указывают на функции. Если записать имя функции без скобок, интерпретатор будет считать, что подразумевается ссылка на объект, благодаря чему имеется возможность передавать такие ссылки на объекты точно так же, как ссылки на любые другие объекты.
Этот факт можно использовать для замены условных инструкций !1, содержащих множественные предложения е11(, единственным вызовом функции. В главе 11 мы будем рассматривать интерактивную консольную про- грамму с именем т!ит!а-т(Ьт.ру, которая имеет следующее меню: (А)бб (Е)б!т (с)!ат (н)ееоче (1)прог! е(х)рог! (0)п11 В программе имеется функция, которая получает символ, выбранный пользователем, и возвращает только допустимый символ, в данном случае «а», «е», «1», «г», «1», «х» или «с(».
Ниже приводятся два эквивалентных фрагмента программного кода, которые, в зависимости от сделанного выбора, вызывают соответствующую функцию: Выбор, сделанный пользователем, хранится в виде строки из одного символа в переменной асс!оп, а ссылка на используемую базу данных— в переменной бЬ. В имя функции 1ерогт () включен завершающий символ подчеркивания, чтобы отличить ее от инструкции !эрот 1. Фрагмент справа создает словарь, ключами которого являются допустимые варианты выбора, а значениями — ссылки на функции.
Вторая инструкция в этом фрагменте извлекает ссылку на функцию, соответствующую выбранному действию, и вызывает ее с помощью оператора вызова (), передавая аргумент бЬ. Фрагмент справа не только короче, но и легко масштабируется (в словаре может быть гораздо больше элементов) без потерь производительности, в отличие от фрагмента слева, скорость работы которого зависит от того, сколько условий в предложениях е1! г придется проверить, прежде чем будет найдена требуемая функция. тг асс!оп == "а": абб бчб(бо) Е!!Г аот1Оп == "Е": ебтт бчб(бЬ) е!тг асттоп == "!": Мзт бчбз(бЬ) е1т! аст1оп == "г'.
гееоче бчб(бЬ) е!!т аст1оп == "!"; !прог! (бЬ) е1тт асттоп == "х": ехрогт(бЬ) е1!г асс!оп == "ц": цют(бЬ) гчпст!опа = бтст(а=асс бчб, Е=Еб!т бчб, 1=!тат ачба, г=гееоче бчб, 1=!прог!, х=ехрогт, ц=цч11) гчпст1ога[асыоп)(бь) 397 Упучшенные приемы процедурного программирования Этот прием уже использовался в программе сапожек!-!псЫепгв ру из пре- дыдущей главы — в методе !прог! ( ), как показано в выдержке из этого метода ниже: са11 = ((".атх", "боа"): ве1(.!прог! ха1 боа, (".атх", "етгее"): ве1(.!прог! хп1 етгее, (".атх", "вах"), ве1Г ьзрогт хи1 вах, (".атт", "аапоа1"): ве1(.!прог! (ехт аапоа1, (".а1!", "гедех"): ве11.1ерог! техт гедех, (".ать", попе): ве1(.!прог! ыпагу, (".а1р", нопе): ве1(.!прог! ртск1е) гево1! = са11(ехтепв!оп, геабег)((11епаае) Всего метод содержит 13 строк программного кода.
Значение ех!епв)оп определяется в самом методе, а значение геабег передается вызывающей программой. Ключами словаря являются двухэлементные кортежи, а значениями — методы. Если бы в этом случае использовались инструкции тт, реализация метода выросла бы до 22 строк, а понятие масштабируемости к реализации было бы вообще неприменимо. Выражения-генераторы и функции-генераторы В главе 6 мы познакомились с функциями-генераторами Функции- и методами-генераторами.
Кроме того, существует воз- генераторы, можность создавать еще и выражения-генераторы. Син- стр. 324 таксически они очень похожи на генераторы списков, единственное отличие состоит в том, что они заключаются не в квадратные скобки, а в круглые. Ниже приводится синтаксис выражений-генераторов в общем виде: (ехргевюоп Гог ттеи 1п ттегаЫе) (ехргеввтоп Гог !Ген !и ттегаЫе тт сопштвоп) бег !теис тп кеу огбег(б): гетега ((кеу, б(кеу)) гог кеу 1п вогтеб(б)) бет !геев 1п Кеу огбег(б): гог кеу !п вогтеб(б); уте1б кеу, б(кеу] Обе функции возвращают генератор, который воспроизводит список элементов «ключ-значение» для заданного словаря. Если потребуется получить сразу весь список элементов, возвращаемый функциями генератор можно передать функции 1!в!() или !ор1е(), или, наоборот, выполнять итерации через генератор, извлекая элементы по мере необходимости.
Генераторы представляют собой средство выполнения отложенных вычислений, то есть значения вычисляются, только когда они дейст- В предыдущей главе мы создавали методы-генераторы, используя инструкцию уте1б. Ниже приводятся два эквивалентных фрагмента программного кода, демонстрирующие, как простой цикл (ог ... тп, содержащий выражение уте1б, можно превратить в генератор: 398 Глава 8. Усовершенствованные приемы программирозанип вительно необходимы. Такой подход может оказаться гораздо эффективнее, чем, например, вычисление содержимого огромного списка за один раз.
Некоторые генераторы могут воспроизводить столько значений, сколько потребуется — без ограничения сверху. Например: ает цоагтегв(пах( цоагтег=О.О): нП11а Тгое: у1е10 пах( цоагтег пехт цоагтег а= 0.25 Эта функция будет возвращать числа 0.0, 0.25, О. б и т. д. до бесконечности. Ниже показано, как можно было бы использовать такой генератор: гаво11 = [) Гог х тп цоагтвгв(): гаво1(.аррапа(х) 11 х >= 1.0: Ьгаах Применение инструкции Ьгеак здесь очень существенно — без нее цикл (ог ... [п был бы бесконечным. После выхода из цикла переменная гево11 будетсодержатьсписок [0.0, 0.25, 0.5, 0.75, 1,0).
Всякий раз, когда вызывается функция цоагтегв(), она возвращает генератор, начинающий счет с 0.0 и на каждом шаге увеличивающий значение на 0.25, но как быть, если требуется, чтобы генератор начал воспроизводить последовательность с текущего значенияу Сделать это можно, передав требуемое значение в генератор, как показано в новой версии функции-генератора: Оет цоагтагв(пахт цоагтег=0.0). на11а Тгое: гаса(чеа = (у1а10 пехт цоагтег) 1( гасаачеа тв попа: пехт цоагтаг += 0.25 е1ве.' пехт цоагтаг = гаса)чаа Выражение уте10 поочередно возвращает каждое значение вызывающей программе.