Учебник Python 3.1. Учебник Python 3. Учебник Python 1 Материал из Викиучебника. Оглавление
Скачать 1.85 Mb.
|
raise Класс raise Экземпляр В первой форме, Класс должен быть экземпляром типа или класса, производного от него. Первая форма является краткой записью следующего кода: raise Class() Класс в блоке except является сопоставимым с исключением, если является этим же классом или самим по себе базовым классом (никаких других способов обхода — описанный в блоке except производный класс не сопоставим с базовым). Например, следующий код выведет B, C, D в этом порядке: class B( Exception ): pass class C(B): pass class D(C): pass for c in [B , C , D]: try : raise c() except D: ( "D" ) except C: 74 Учебник Python 3.1: Материал из Викиучебника. ( "C" ) except B: ( "B" ) Обратите внимание, что если бы блоки except шли в обратном порядке (начиная с " except B "), код вывел бы B, B, B — сработал бы первый совпадающий блок except При выводе сообщения об ошибке о необработанном исключении, выводится класс исключения, затем двоеточие и пробел, и наконец экземпляр, приведённый к строке за счёт встроенной функции str() Итераторы К этому моменту вы, возможно, заметили, что используя оператор for можно организовать цикл по большинству объектов-контейнеров: for element in [ 1 , 2 , 3 ]: (element) for element in ( 1 , 2 , 3 ): (element) for key in { 'один' : 1 , 'два' : 2 }: (key) for char in "123" : (char) for line in open ( "myfile.txt" ): (line) Такой стиль доступа к элементам прост, лаконичен и удобен. Использованием итераторов (iterators) пропитан язык Python, и это его выделяет среди других. Негласно, оператор for вызывает метод iter() объекта-контейнера. Функция возвращает объект итератора, который определяет метод __next__() , который по очереди получает доступ к элементам в контейнере, по одному за раз. Если больше не остаётся элементов, метод __next__() порождает исключение StopIteration , которое сообщает оператору for о необходимости завершения прохода. Вы можете вызывать метод __next__() посредством встроенной функции next() ; следующий пример показывает, как это работает: >>> s = 'абв' >>> it = iter (s) >>> it < iterator object at 0x00A1DB50 > >>> next(it) 'а' >>> next(it) 'б' >>> next(it) 'в' >>> next(it) Traceback (most recent call last): File " , line 1 , in ? next(it) StopIteration Ознакомившись с механизмами, скрытыми за протоколом итераторов, легко добавить возможность итерирования к вашим классам. Определите метод __iter__() , который возвращает объект с методом next() . Если класс определяет и метод next() , тогда __iter__() может просто возвращать self 75 Учебник Python 3.1: Материал из Викиучебника. class Reverse: "Итератор по последовательности в обратном направлении" def __init__ ( self , data): self .data = data self .index = len (data) def __iter__ ( self ): return self def __next__( self ): if self .index == 0 : raise StopIteration self .index = self .index - 1 return self .data[ self .index] >>> for char in Reverse( 'спам' ): (char) м а п с Генераторы Генераторы (generators) — простой и мощный инструмент для создания итераторов. Они записываются как обычная функция, но где бы им ни было необходимо вернуть данные, используется оператор yield . Каждый раз, когда над ним вызывается next() , генератор возвращается к месту, где он был оставлен (он запоминает все значения данных, а также какой оператор был выполнен последним). Пример показывает, что создание генераторов может быть тривиально простым: def reverse(data): for index in range ( len (data)- 1 , - 1 , - 1 ): yield data[index] >>> for char in reverse( 'гольф' ): (char) ф ь л о г Всё, что можно сделать с использованием генераторов, может быть сделано с использованием основанных на итераторах классов, как описано в предыдущем разделе. Благодаря автоматическому созданию методов __iter__() и __next__() генераторы так компактны. Другая важная особенность состоит в том, что между вызовами сохраняются локальные переменные и состояние выполнения (execution state). Это позволяет конструкциям функций быть проще, а получению переменных экземпляров быть намного легче, нежели с использованием self.index и self.data В дополнение к автоматическому созданию методов и сохранению состояния, когда генераторы заканчивают своё действие, они автоматически порождают исключение StopIteration . В комбинации, эти особенности позволяют легко создавать итераторы не прилагая усилий больших, чем нужно для написания обычной функции. 76 Учебник Python 3.1: Материал из Викиучебника. Выражения-генераторы Некоторые простые генераторы могут быть сжато закодированы в выражении с использованием синтаксиса, схожего со списковыми сборками, но с круглыми скобками заместо квадратных. Выражения-генераторы разработаны в основном для случаев, когда генератор тут же используется в качестве аргумента функции. Выражения с генераторами более компактные, но менее гибкие чем полные определения генераторов и обычно используют память экономнее, чем эквивалентные списковые сборки. Примеры [58] : >>> sum (i*i for i in range ( 10 )) # сумма квадратов 285 >>> xvec = [ 10 , 20 , 30 ] >>> yvec = [ 7 , 5 , 3 ] >>> sum (x*y for x , y in zip (xvec , yvec)) # скалярное произведение 260 >>> from math import sin , radians >>> sine_table = {x: sin(radians(x)) for x in range ( 0 , 91 )} >>> unique_words = set (word for line in page for word in line.split()) >>> valedictorian = max ((student.gpa , student.name) for student in graduates) >>> data = 'golf' >>> list (data[i] for i in range ( len (data)- 1 , - 1 , - 1 )) [ 'f' , 'l' , 'o' , 'g' ] Краткий обзор стандартной библиотеки Взаимодействие с операционной системой Модуль os предоставляет десятки функций для взаимодействия с операционной системой. >>> import os >>> os .getcwd() # возвращает путь к текущему каталогу 'C: \\ Python31' >>> os .system( 'dir *.txt' ) # выполнить указанную команду ОС ...список текстовых файлов , выведенных командой... 0 >>> os .chdir( '/server/accesslogs' ) # сменить текущий каталог Лучше всего применять import os вместо from os import * . Это предохранит встроенную функцию open() от замещения функцией os.open() , имеющей несколько иное назначение. В интерактивном режиме встроенные функции dir() и help() помогут разобраться с большими модулями вроде os: >>> import os >>> dir ( os ) ...список всех атрибутов модуля... >>> help ( os ) ...страница руководства по модулю на основе строк документации... Для управления файлами и каталогами удобный высокоуровневый интерфейс предоставляет модуль shutil: >>> import shutil >>> shutil .copyfile( 'data.db' , 'archive.db' ) # копировать файл 77 Учебник Python 3.1: Материал из Викиучебника. >>> shutil .move( '/build/executables' , 'installdir' ) # переместить каталог Wildcard-шаблоны для имён файлов Модуль glob предоставляет функцию для получения списка файлов на основе заданного шаблона: >>> import glob >>> glob glob ( '*.py' ) [ 'primes.py' , 'random.py' , 'quote.py' ] Аргументы командной строки Сценарии общего назначения часто нуждаются в аргументах командной строки. Эти аргументы хранятся в атрибуте argv модуля sys в виде списка. Например, при запуске python demo.py one two three в командной строке шелла для сценария demo.py: import sys ( sys .argv) будет выведено ['demo.py', 'one', 'two', 'three'] Модуль getopt обрабатывает sys.argv , используя соглашения функции getopt() системы Unix. Более мощную и гибкую обработку аргументов командной строки осуществляет модуль optparse. Стандартный вывод. Завершение сценария Модуль sys имеет атрибуты stdin , stdout и stderr (для стандартного ввода, вывода и вывода ошибок соответственно). Последний может быть полезен для вывода предупреждений и сообщений об ошибках когда стандартный вывод перенаправлен [59] : >>> sys .stderr.write( 'Внимание! Файл журнала не найден. \n ' ) Внимание ! Файл журнала не найден. 34 Для завершения сценария можно использовать sys.exit() Сравнение строк по шаблонам Модуль re предоставляет инструментарий для работы с регулярными выражениями для нетривиальной обработки текста. С помощью регулярных выражений можно создавать выразительные и оптимизированные решения для поиска и обработки строк. >>> import re >>> re .findall(r ' \b f[a-z]*' , 'which foot or hand fell fastest' ) [ 'foot' , 'fell' , 'fastest' ] >>> re .sub(r '( \b [a-z]+) \1 ' , r ' \1 ' , 'cat in the the hat' ) 'cat in the hat' Когда требуются более простые возможности, методы строковых объектов предпочтительнее, так как их легче читать и отлаживать: >>> 'чай для двоих' .replace( 'для' , 'на' ) 'чай на двоих' Математические функции Модуль math предоставляет доступ к библиотеке языка C для функций над числами с плавающей запятой: >>> import math >>> math .cos( math .pi / 4 ) 0.70710678118654757 >>> math .log( 1024 , 2 ) 78 Учебник Python 3.1: Материал из Викиучебника. 10.0 С помощью модуля random можно делать случайный выбор: >>> import random >>> random .choice([ 'яблоко' , 'груша' , 'банан' ]) 'яблоко' >>> random .sample( range ( 100 ) , 10 ) # выборка без повторений [ 30 , 83 , 16 , 4 , 8 , 81 , 41 , 50 , 18 , 33 ] >>> random random () # случайное число с плавающей запятой 0.17970987693706186 >>> random .randrange( 6 ) # случайное целое из диапазона range(6) 4 >>> random .sample([ 1 , 2 , 3 , 4 , 5 ] , 3 ) # случайные три элемента из списка [ 4 , 1 , 5 ] Проект SciPy < http://scipy.org > имеет много других модулей для численных расчётов. Протоколы интернет В стандартной библиотеке имеется целый набор модулей для различных сервисов и протоколов интернет. Наиболее употребимыми можно считать urllib.request для получения данных по заданному адресу (URL) и smtplib для отправки сообщений электронной почты: >>> from urllib .request import urlopen >>> for line in urlopen( 'http://tycho.usno.navy.mil/cgi-bin/timer.pl' ): if 'EST' in line or 'EDT' in line: # временные зоны (line) < BR > Nov. 25 , 09 : 43 : 32 PM EST >>> import smtplib >>> server = smtplib .SMTP( 'localhost' ) >>> server.sendmail( 'soothsayer@example.org' , 'jcaesar@example.org' , """To: jcaesar@example.org ... From: soothsayer@example.org ... Beware the Ides of March. ... """ ) >>> server.quit() Заметьте, что второй пример требует почтового сервера на той же машине. Дата и время Модуль datetime предлагает классы для работы с датами и временем как в простых, так и сложных случаях. Кроме поддержки календарной арифметики, реализация обращает особенное внимание на эффективность вычисления составных частей для вывода и дальнейших манипуляций. Модуль также предлагает объекты с поддержкой временных зон. # даты можно легко составлять и выводить в требуемом формате >>> from datetime import date >>> now = date.today() >>> now datetime .date( 2009 , 2 , 3 ) >>> now.strftime( "%d.%m.%Y" ) '03.02.2009' # даты поддерживают календарную арифметику 79 Учебник Python 3.1: Материал из Викиучебника. >>> birthday = date( 1964 , 7 , 31 ) >>> age = now - birthday >>> age.days 16258 Сжатие данных и архивы Наиболее распространённые форматы сжатия и архивации напрямую поддерживаются модулями стандартной библиотеки: zlib, gzip, bz2, zipfile и tarfile. >>> import zlib >>> s = "Закрой замок на замок, чтобы замок не замок" >>> len ( bytes (s , "utf-8" )) 78 >>> t = zlib .compress(s) >>> len (t) 54 >>> ( str ( zlib .decompress(t) , "utf-8" )) Закрой замок на замок , чтобы замок не замок >>> zlib .crc32(s) 2392363341 Измерение производительности Некоторым пользователям Python интересно знать относительную производительность различных подходов к решению одной и той же проблемы. Python предлагает инструмент для немедленного ответа на эти вопросы. Например, очень заманчиво использовать присваивание кортежей вместо традиционного подхода к замене значений переменных местами. Модуль timeit быстро продемонстрирует незначительное превосходство кортежей: >>> from timeit import Timer >>> Timer( 'a, b = b, a' , 'a=1; b=2' ). timeit () 0.15707302093505859 >>> Timer( 't=a; a=b; b=t' , 'a=1; b=2' ). timeit () 0.19421601295471191 В отличие от высокого разрешения модуля timeit , модули profile и pstats предлагают возможность обнаружить критические по времени участки в больших фрагментах кода. Контроль качества Один из подходов к разработке высококачественного программного обеспечения заключается в написании тестов для каждой функции при её разработке и регулярном запуске этих тестов во время всего процесса разработки. Модуль doctest имеет средства для просмотра модуля и проверки результатов тестов, заложенных в строках документации. Написание теста для функции заключается в копировании и вставке типичного вызова функции и ее результатов в строку документации. Это улучшает документацию, предоставляя пользователю реальный пример, а модуль doctest проверяет, что код соответствует документации. def average(values): """Вычисляет среднее арифметическое списка чисел. >>> print(average([20, 30, 70])) 40.0 """ 80 Учебник Python 3.1: Материал из Викиучебника. return sum (values) / len (values) import doctest doctest .testmod() # автоматически проверяет тесты в документации Модуль unittest не менее прост в использовании чем doctest , но позволяет создавать более полный набор тестов, располагающийся в отдельном файле: import unittest class TestStatisticalFunctions( unittest .TestCase): def test_average( self ): self .assertEqual(average([ 20 , 30 , 70 ]) , 40.0 ) self .assertEqual( round (average([ 1 , 5 , 7 ]) , 1 ) , 4.3 ) self .assertRaises( ZeroDivisionError , average , []) self .assertRaises( TypeError , average , 20 , 30 , 70 ) unittest .main() # Вызов из командной строки выполняет проверку всех тестов этого модуля «Батарейки в комплекте» Python руководствуется философией «батарейки в комплекте». Это можно проследить по сложным и устойчивым к ошибкам возможностям его пакетов побольше. Примеры: • Модули xmlrpc.client и xmlrpc.server делают реализацию удалённых вызовов почти тривиальной задачей. Несмотря на названия, знания об обработке XML не требуются. • Пакет email — это библиотека для работы с сообщениями электронной почты, включая MIME и другие основанные на RFC 2822 документы-сообщения. В отличие от smtplib и poplib , которые занимаются непосредственно отправкой и приёмом сообщений, пакет email является полным набором инструментов для построения и декодирования сообщений сложной структуры (включая вложения) и для реализации интернетного кодирования и протокола заголовков. • Пакеты xml.dom и xml.sax предоставляют ошибко-устойчивую поддержку парсинга XML — этого популярного формата для обмена данными. Аналогично, модуль csv поддерживает чтение и запись в распространённом формате баз данных. Вместе эти модули серьёзно облегчают обмен данными между приложениями на Python и другими приложениями. • Интернационализация поддерживается благодаря ряду модулей, включая gettext , locale и пакет codecs Второй краткий обзор стандартной библиотеки |