Главная страница

справочник по Python. мм isbn 9785932861578 9 785932 861578


Скачать 4.21 Mb.
Названиемм isbn 9785932861578 9 785932 861578
Анкорсправочник по Python
Дата08.05.2022
Размер4.21 Mb.
Формат файлаpdf
Имя файлаBizli_Python-Podrobnyy-spravochnik.440222.pdf
ТипСправочник
#518195
страница26 из 82
1   ...   22   23   24   25   26   27   28   29   ...   82
Глава
15
.
Структуры данных, алгоритмы
и упрощение программного кода
М
одули, о которых рассказывается в этой главе, используются для реше- ния типичных задач программирования и имеют отношение к определе- нию структур данных, реализации алгоритмов и позволяют упростить программный код за счет использования итераций, функционального про- граммирования, менеджеров контекста и классов. Эти модули следует рас- сматривать, как расширения встроенных типов и функций языка Python.
Во многих случаях внутренняя реализация обладает чрезвычайно высо- кой эффективностью и лучше подходит для решения различных проблем, чем встроенные типы и функции.
Модуль abc
Модуль abc объявляет метакласс и пару декораторов, с помощью которых определяются новые абстрактные базовые классы.
ABCMeta
Метакласс, являющийся представлением абстрактного базового клас- са. Чтобы определить абстрактный базовый класс, необходимо объявить класс, использующий метакласс ABCMeta. Например:
import abc class Stackable: # В Python 3 используется синтаксис
__metaclass__ = abc.ABCMeta # class Stackable(metaclass=abc.ABCMETA)
...
Классы, созданные таким способом, имеют следующие важные отличия от обычных классов:
• Во-первых, если в абстрактном классе объявляются методы или свой- ства с использованием декораторов @abstractmethod и @abstractproperty, описываемых ниже, то экземпляры производных классов не могут быть созданы, если эти классы не имеют неабстрактных реализаций этих ме- тодов и свойств.

Модуль abc
327
• Во-вторых, абстрактные классы обладают методом класса register(sub-
class)
, который может использоваться для регистрации дополнительных типов как логических подклассов. Для любого подкласса, зарегистриро- ванного с помощью этого метода, вызов isinstance(x, AbstractClass) будет возвращать True, если x является экземпляром этого подкласса.
• Наконец, абстрактные классы могут объявлять специальный метод класса __subclasshook__(cls, subclass). Этот метод должен возвращать
True
, если тип класса subclass может считаться подклассом класса cls,
False
– если класс subclass не является подклассом cls, или возбуждать исключение NotImplemented, если невозможно сделать никаких предпо- ложений о принадлежности класса subclass к иерархии.
abstractmethod(method)
Декоратор, который объявляет метод method абстрактным. Когда этот деко- ратор используется в абстрактном базовом классе, классы, непосредствен- но объявленные как производные этого базового класса, могут использо- ваться для создания экземпляров, только если они включают неабстракт- ное определение метода method. Этот декоратор не оказывает влияния на подклассы, зарегистрированные с помощью метода register() абстрактного базового класса.
abstractproperty(fget [, fset [, fdel [, doc]]])
Создает абстрактное свойство. Этот декоратор принимает те же аргументы, что и обычная функция property(). Когда этот декоратор используется в аб- страктном базовом классе, классы, непосредственно объявленные как про- изводные этого базового класса, могут использоваться для создания экзем- пляров, только если они включают неабстрактное определение свойства.
В следующем фрагменте приводится пример объявления простого аб- страктного класса:
from abc import ABCMeta, abstractmethod, abstractproperty class Stackable: # В Python 3 используется синтаксис
__metaclass__ = ABCMeta # class Stackable(metaclass=ABCMeta)
@abstractmethod def push(self,item):
pass
@abstractmethod def pop(self):
pass
@abstractproperty def size(self):
pass
Ниже приводится пример класса, производного от класса Stackable:
class Stack(Stackable):
def __init__(self):
self.items = []
def push(self,item):
self.items.append(item)
def pop(self):
return self.items.pop()

328
Глава 15. Структуры данных, алгоритмы и упрощение программного кода
Н
иже показано сообщение об ошибке, которое выводится при попытке соз- дать экземпляр класса Stack:
>>> s = Stack()
Traceback (most recent call last):
File “”, line 1, in
TypeError: Can’t instantiate abstract class Stack with abstract methods size
(Перевод:
Трассировочная информация (самый последний вызов – самый нижний):
Файл “”, строка 1, в <модуль>
TypeError: Невозможно создать экземпляр абстрактного класса Stack с абстрактным методом size
)
>>>
Чтобы исправить эту ошибку, необходимо добавить определение свойства size()
в класс Stack. Сделать это можно, либо изменив объявление самого класса Stack, либо объявив производный класс и добавив в него необходи- мые объявления свойств и методов:
class CompleteStack(Stack):
@property def size(self):
return len(self.items)
Ниже приводится пример использования законченного объекта стека:
>>> s = CompleteStack()
>>> s.push(“foo”)
>>> s.size
1
>>>
См. также
Глава 7 «Классы и объектно-ориентированное программирование», описание мо- дуля numbers в главе 14 (стр. 321) и описание модуля collections ниже, в этой главе
(стр. 332).
Модуль array
В модуле array объявляется новый тип объектов – array, который действует практически так же, как список, но все его элементы могут принадлежать только одному какому-нибудь типу. Тип элементов массива определяется в момент создания с помощью одного из кодов, перечисленных в табл. 15.1.
Таблица 15.1. Коды типов
Код типа
Описание
Тип в языке C
Минимальный размер
(в байтах)
‘c’
8-битный символ char
1
‘b’
8-битное целое signed char
1

Модуль array
329
Код типа
Описание
Тип в языке C
Минимальный размер
(в байтах)
‘B’
8-битное целое без знака unsigned char
1
‘u’
Символ Юникода
PY_UNICODE
2 или 4
‘h’
16-битное целое short
2
‘H’
16-битное целое без знака unsigned short
2
‘i’
Целое int
4 или 8
‘I’
Целое без знака unsigned int
4 или 8
‘l’
Длинное целое long
4 или 8
‘L’
Длинное целое без знака unsigned long
4 или 8
‘f’
Число с плавающей точкой одинарной точ- ности float
4
‘d’
Число с плавающей точкой двойной точ- ности double
8
Формат представления целых и длинных целых чисел определяется аппа- ратной архитектурой (это могут быть 32- или 64-битные значения). Когда тип элементов массива определяется кодом ‘L’ или ‘I’, в языке Python 2 они возвращаются, как длинные целые числа.
В модуле определяется следующий тип данных:
array(typecode [, initializer])
Создает массив элементов типа typecode. В необязательном аргументе ini-
tializer
передается строка или список значений, используемых для ини- циализации значений элементов массива. Объект a типа array имеет сле- имеет сле- сле- сле- дующие атрибуты и методы:
Атрибут или метод
Описание
a.typecode
Символ с кодом типа, который использовался при созда- нии массива.
a.itemsize
Размер элемента массива (в байтах).
a.append(x)
Добавляет в конец массива новый элемент со значением x.
a.buffer_info()
Возвращает кортеж (address, length), содержащий адрес и размер буфера в памяти, выделенного для хранения массива.
a.byteswap()
Меняет порядок следования байтов во всех элементах массива с прямого на обратный, или наоборот. Поддержи- вается только для целочисленных значений.

330
Глава 15. Структуры данных, алгоритмы и упрощение программного кода
Атрибут или метод
Описание
a.count(x)
Возвращает количество вхождений x в массиве a.
a.extend(b)
Добавляет объект b в конец массива a. Объект b может
быть массивом или другим итерируемым объектом, тип
элементов которого совпадает с типом элементов мас-
сива a
.
a.fromfile(f, n)
Читает n элементов (в двоичном формате) из объекта фай- ла f и добавляет их в конец массива. Аргумент f должен быть объектом файла. Если количество элементов, кото- рое удалось прочитать из файла, окажется меньше, чем n, возбуждает исключение EOFError.
a.fromlist(list)
Добавляет элементы из списка list в конец массива a. Ар- гумент list может быть итерируемым объектом.
a.fromstring(s)
Добавляет элементы из строки s в конец массива, где s ин- терпретируется как строка двоичных значений, как если бы чтение выполнялось методом fromfile().
a.index(x)
Возвращает индекс первого вхождения значения x в мас- сиве a. В случае отсутствия значения x возбуждает исклю- чение ValueError.
a.insert(i, x)
Вставляет новый элемент со значением x перед элементом с индексом i.
a.pop([i])
Удаляет из массива элемент с индексом i и возвращает его. Если аргумент i опущен, удаляет последний элемент.
a.remove(x)
Удаляет первое вхождение x из массива. В случае отсут- ствия значения x возбуждает исключение ValueError.
a.reverse()
Переставляет элементы массива в обратном порядке.
a.tofile(f)
Записывает все элементы массива в файл f. Данные со- храняются в двоичном формате.
a.tolist()
Преобразует массив в обычный список.
a.tostring()
Преобразует массив в строку двоичных данных, как если бы запись выполнялась методом tofile().
a.tounicode()
Преобразует массив в строку Юникода. Возбуждает ис- ключение ValueError, если элементы массива имеют тип, отличный от ‘u’.
При попытке вставить в массив элементы, тип которых не совпадает с ти- пом, использовавшимся при создании массива, возбуждается исключение
TypeError
Модуль array может пригодиться, когда потребуется реализовать списки данных с эффективным расходованием памяти и известно, что все элемен- ты списка принадлежат одному типу. Например, чтобы сохранить список из 10 миллионов целых чисел, потребуется примерно 160 Мбайт памяти, тогда как массив из 10 миллионов целых чисел займет всего 40 Мбайт. Не-
(продолжение)

Модуль bisect
331
смотря на такую экономию памяти, ни одна из основных операций над мас- сивами не выполняется быстрее, чем аналогичные операции над списка- ми, более того, они могут оказаться даже медленнее.
При выполнении вычислений с участием массивов следует быть осторож- ными с операциями, которые создают списки. Например, когда генераторы списков применяются к массивам, они преобразуют их в списки целиком, уничтожая все преимущества в экономии памяти. В подобных ситуациях создавать новые массивы лучше с помощью выражений-генераторов. На- пример:
a = array.array(“i”, [1,2,3,4,5])
b = array.array(a.typecode, (2*x for x in a)) # Создаст новый массив из a
Поскольку выигрыш от использования массивов заключается в экономии памяти, возможно, окажется более осмысленным выполнить операции не- посредственно в исходном массиве. Функция enumerate() обеспечивает эф- фективный способ реализации таких операций, например:
a = array.array(“i”, [1,2,3,4,5])
for i, x in enumerate(a):
a[i] = 2*x
В случае больших массивов операции внутри массива выполняются при- мерно на 15 процентов быстрее, чем аналогичный программный код, кото- рый создает новый массив с помощью выражения-генератора.
Примечания
Массивы, создаваемые с помощью этого модуля, не поддерживают матрич- ные или векторные операции. Например, оператор добавления не добав- ляет соответствующие элементы массивов – он просто добавит один мас- сив в конец другого. Создавать массивы, позволяющие экономить память и обеспечивающие высокую эффективность операций, можно с помощью расширения numpy, доступного по адресу http://numpy.sourceforge.net/. Об- ратите внимание, что это расширение имеет совершенно иной прикладной интерфейс.
Для добавления содержимого одного массива в конец другого можно ис- пользовать оператор +=. Создавать дубликаты содержимого можно с помо- щью оператора *=.
См. также
Описание модуля struct (стр. 366).
Модуль bisect
Модуль bisect обеспечивает возможность поддержания списков в отсорти- рованном состоянии. В своей работе он опирается в основном на использо- вание алгоритма двоичного поиска.

332
Глава 15. Структуры данных, алгоритмы и упрощение программного кода
bisect(list, item [, low [, high]])
Возвращает индекс в списке list, куда следует вставить значение item, чтобы сохранить этот список в отсортированном порядке. Аргументы low и high определяют индексы начала и конца области поиска в списке. Если значение items уже присутствует в списке, возвращаемый индекс всегда бу- дет правее существующего элемента списка.
bisect_left(list, item [, low [, high]])
Возвращает индекс в списке list, куда следует вставить значение item, чтобы сохранить этот список в отсортированном порядке. Аргументы low и high определяют индексы начала и конца области поиска в списке. Если значение items уже присутствует в списке, возвращаемый индекс всегда бу- дет левее существующего элемента списка.
bisect_right(list, item [, low [, high]])
То же, что и функция bisect().
insort(list, item [, low [, high]])
Вставляет элемент item в список list с учетом порядка сортировки. Если значение item уже присутствует в списке, новый элемент вставляется пра- вее его.
insort_left(list, item [, low [, high]])
Вставляет элемент item в список list с учетом порядка сортировки. Если значение item уже присутствует в списке, новый элемент вставляется левее его.
insort_right(list, item [, low [, high]])
То же, что и insort().
Модуль collections
Модуль collections содержит оптимизированные реализации нескольких контейнерных типов, абстрактные базовые классы для различных типов контейнеров и вспомогательные функции для создания именованных кор- тежей. Все это описывается в следующих разделах.
Типы данных deque и defaultdict
Модуль collections объявляет два новых типа контейнеров: deque и default- dict
deque([iterable [, maxlen]])
Тип данных, представляющий двустороннюю очередь (название типа deque произносится «дек»). В аргументе iterable передается итерируемый объект, используемый для заполнения очереди deque. Двусторонняя очередь позво- ляет добавлять и удалять элементы из любого конца очереди. Реализация очередей оптимизирована так, что эти операции имеют примерно одинако- вую производительность (O(1)). Этим очереди выгодно отличаются от спи- сков, где выполнение операций в начале списка может потребовать выпол-

Модуль collections
333
нить сдвиг всех элементов, расположенных правее элемента, над которым выполняется операция. Если передается необязательный аргумент maxlen, возвращаемый объект deque превращается в кольцевой буфер указанного размера. То есть при добавлении нового элемента в очередь, в которой уже не осталось свободного места, производится удаление элемента с противо- положного конца, чтобы освободить место.
Экземпляр d типа deque имеет следующие методы:
d.append(x)
Добавляет объект x с правой стороны очереди d.
d.appendleft(x)
Добавляет объект x с левой стороны очереди d.
d.clear()
Удаляет все элементы из очереди d.
d.extend(iterable)
Расширяет очередь d, добавляя с правой стороны все элементы из итерируе- мого объекта iterable.
d.extendleft(iterable)
Расширяет очередь d, добавляя с левой стороны все элементы из итерируе- мого объекта iterable. Из-за того, что добавление производится последова- тельно, по одному элементу, элементы итерируемого объекта iterable будут добавлены в очередь d в обратном порядке.
d.pop()
Удаляет и возвращает элемент с правой стороны очереди d. Если очередь пуста, возбуждает исключение IndexError.
d.popleft()
Удаляет и возвращает элемент с левой стороны очереди d. Если очередь пу- ста, возбуждает исключение IndexError.
d.remove(item)
Удаляет первое вхождение элемента item. Возбуждает исключение ValueEr- ror
, если указанное значение не будет найдено.
d.rotate(n)
Прокручивает все элементы на n позиций вправо. Если в аргументе n пере- дается отрицательное значение, прокручивание выполняется влево.
Двусторонние очереди часто незаслуженно забываются многими програм- мистами. Однако этот тип данных предлагает множество преимуществ.
Во-первых, очереди этого типа отличаются весьма эффективной реализа- цией, даже на уровне использования внутренних структур данных, обеспе- чивающих оптимальное использование кэша процессора. Добавление но- вых элементов в конец выполняется немногим медленнее, чем во встроен- ных списках, зато добавление в начало выполняется существенно быстрее.
Кроме того, операции добавления новых элементов в двусторонние очереди реализованы с учетом возможности их использования в многопоточных

334
Глава 15. Структуры данных, алгоритмы и упрощение программного кода приложениях, что делает этот тип данных привлекательным для реали- зации очередей. Двусторонние очереди поддерживают также возможность сериализации средствами модуля pickle.
defaultdict([default_factory], ...)
Тип данных, который практически в точности повторяет функциональ- ные возможности словарей, за исключением способа обработки обраще- ний к несуществующим ключам. Когда происходит обращение к несуще- к несуществующим ключам. Когда происходит обращение к несуще- к несуществующим ключам. Когда происходит обращение к несуще- несуществующим ключам. Когда происходит обращение к несуще- несуществующим ключам. Когда происходит обращение к несуще- ключам. Когда происходит обращение к несуще- ключам. Когда происходит обращение к несуще-
. Когда происходит обращение к несуще-
Когда происходит обращение к несуще- происходит обращение к несуще- происходит обращение к несуще- обращение к несуще- обращение к несуще- к несуще- к несуще- несуще- несуще- ствующему ключу, вызывается функция, которая передается в аргумен- ключу, вызывается функция, которая передается в аргумен- ключу, вызывается функция, которая передается в аргумен-
, вызывается функция, которая передается в аргумен- вызывается функция, которая передается в аргумен- функция, которая передается в аргумен- функция, которая передается в аргумен-
, которая передается в аргумен- которая передается в аргумен- передается в аргумен- передается в аргумен- в аргумен- в аргумен- аргумен- аргумен- те default_factory. Эта функция должна вернуть значение по умолчанию, которое затем сохраняется как значение указанного ключа. Остальные аргументы функции defaultdict() в точности те же самые, что передаются встроенной функции dict(). Экземпляры типа defaultdict обладают теми же возможностями, что и встроенные словари. Атрибут default_factory со- держит функцию, которая передается функции в первом аргументе, и мо- жет изменяться в случае необходимости.
Объекты типа defaultdict удобно использовать в качестве словаря для сле- жения за данными. Например, предположим, что необходимо отслеживать позицию каждого слова в строке s. Ниже показано, насколько просто это можно реализовать с помощью объекта defaultdict:
>>> from collections import defaultdict
>>> s = “yeah but no but yeah but no but yeah”
>>> words = s.split()
>>> wordlocations = defaultdict(list)
>>> for n, w in enumerate(words):
...
wordlocations[w].append(n)
...
>>> wordlocations
defaultdict(, {‘yeah’:[0, 4, 8],’but’: [1, 3, 5, 7],’no’: [2, 6]})
>>>
В этом примере операция обращения к элементу словаря wordlocations[w] будет «терпеть неудачу», когда слово встречается впервые. Однако вместо исключения KeyError будет вызвана функция list, переданная в аргументе
default_factory
, которая создаст новое значение. Встроенные словари имеют метод setdefault(), который позволяет добиться того же эффекта, но его ис- пользование делает программный код менее наглядным, и к тому же он ра- ботает медленнее. Например, инструкцию, добавляющую новый элемент в предыдущем примере, можно было бы заменить инструкцией wordloca- tions.setdefault(w,[]).append(n)
. Но она не так очевидна и выполняется почти в два раза медленнее, чем пример с использованием объекта defaultdict.
Именованные кортежи
Кортежи
часто используются для представления простых структур дан- ных. Например, кортежи можно использовать для представления сетевых адресов: addr = (hostname, port). Типичный недостаток кортежей состоит в том, что к отдельным элементам приходится обращаться с помощью чис- ловых индексов, например: addr[0] или addr[1]. Это усложняет чтение про- граммного кода и его сопровождение, потому что приходится запоминать

Модуль collections
335
значение всех индексов (в случае больших кортежей эта ситуация ухудша- ется еще больше).
Модуль collections содержит функцию namedtuple(), которая используется для создания подклассов кортежей, которые позволяют обращаться к сво- им элементам, как к атрибутам.
namedtuple(typename, fieldnames [, verbose])
Создает подкласс типа tuple с именем typename. В аргументе fieldnames пере- дается список имен атрибутов в виде строк. Имена в этом списке должны быть допустимыми идентификаторами Python. Они не должны начинаться с символа подчеркивания, а порядок их следования определяет порядок следования элементов кортежа, например [‘hostname’,’port’]. Кроме того, в аргументе fieldnames допускается передавать строку, такую как ‘hostname port’
или ‘hostname, port’. Возвращаемым значением функции является класс, имя которого передается в аргументе typename. Этот класс можно ис- пользовать для создания экземпляров именованных кортежей. Если в ар- гументе verbose передается значение True, функция выводит определение класса в поток стандартного вывода.
Ниже приводится пример использования этой функци:
>>> from collections import namedtuple
>>> NetworkAddress = namedtuple(‘NetworkAddress’,[‘hostname’,’port’])
>>> a = NetworkAddress(‘www.python.org’,80)
>>> a.hostname
‘www.python.org’
>>> a.port
80
>>> host, port = a
>>> len(a)
2
>>> type(a)

>>> isinstance(a, tuple)
True
>>>
В этом примере создается именованный кортеж NetworkAddress, который ничем не отличается от обычного кортежа, за исключением поддержки воз- можности обращаться к его элементам как к атрибутам, например: a.hostname или a.port. Внутренняя реализация этого класса не использует словарь эк- земпляра и не увеличивает потребление памяти по сравнению с обычными кортежами. Поддерживаются все обычные операции над кортежами.
Именованные кортежи удобно использовать для определения объектов, ко- торые в действительности являются обычными структурами данных. На- пример, вместо класса, такого как показано ниже:
class Stock(object):
def __init__(self,name,shares,price):
self.name = name self.shares = shares self.price = price

336
Глава 15. Структуры данных, алгоритмы и упрощение программного кода
М
ожно было бы определить именованный кортеж:
import collections
Stock = collections.namedtuple(‘Stock’,’name shares price’)
Обе версии действуют практически одинаково. Например, обе версии обе- спечивают доступ к полям с именами s.name, s.shares и так далее. Однако именованные кортежи эффективнее расходуют память и поддерживают различные операции над кортежами, такие как распаковывание элемен- тов (например, если имеется список именованных кортежей, эти кортежи можно будет распаковывать в цикле for, например: for name, shares, price in stockList
). Недостатком именованных кортежей является более низкая скорость операции получения значений атрибутов в сравнении с классами.
Например, обращение к атрибуту s.shares выполняется более чем в два раза медленнее, если s является экземпляром именованного кортежа.
Именованные кортежи широко используются в стандартной библиотеке языка Python, где их применение обусловлено, отчасти, историческими причинами – во многих библиотечных модулях кортежи изначально ис- пользовались в различных функциях для возврата информации о файлах, кадрах стека и другой низкоуровневой информации. Программный код, использующий эти кортежи, не всегда выглядел достаточно элегантным.
Поэтому был выполнен переход к использованию именованных кортежей, что позволило сделать программный код более понятным, без нарушения обратной совместимости. Еще одна проблема именованных кортежей за- ключается в том, что после того, как вы начнете использовать именован- ный кортеж, количество его полей должно оставаться неизменным (то есть, если добавить в кортеж новое поле, прежний программный код, ис- пользующий его, окажется неработоспособным). Разновидности именован- ных кортежей используются в библиотеке для добавления новых полей к данным, возвращаемым некоторыми функциями. Например, объект может изначально поддерживать прежний интерфейс кортежей, а позднее к нему могут быть добавлены дополнительные значения, доступные в виде именованных атрибутов.
Абстрактные базовые классы
В модуле collections определено несколько абстрактных базовых классов.
Назначение их состоит в том, чтобы описать программный интерфейс неко- торых типов контейнеров, таких как списки, множества и словари. Можно выделить два основных случая использования этих классов. Во-первых, они могут использоваться, как базовые классы для пользовательских объ- ектов, имитирующих функциональность встроенных контейнерных ти- пов. Во-вторых, они могут использоваться для проверки типов. Например, если требуется убедиться, что объект s способен действовать как последо- вательность, можно вызвать функцию isinstance(s, collections.Sequence).
Container
Базовый класс всех контейнеров. Определяет единственный абстрактный метод __contains__(), реализующий оператор in.

Модуль collections
337
Hashable
Б
азовый класс всех объектов, которые могут использоваться в качестве клю- чей хеш-таблиц. Определяет единственный абстрактный метод __hash__().
Iterable
Базовый класс объектов, поддерживающих протокол итераций. Определя- ет единственный абстрактный метод __iter__().
Iterator
Базовый класс итерируемых объектов. Определяет абстрактный метод next()
, а также наследует класс Iterable и предоставляет реализацию по умолчанию метода __iter__(), который просто ничего не делает.
Sized
Базовый класс контейнеров, которые позволяют определить размер. Опре- деляет абстрактный метод __len__().
Callable
Базовый класс объектов, поддерживающих возможность вызова, как функции. Определяет абстрактный метод __call__().
Sequence
Базовый класс объектов, которые выглядят как последовательности. На- следует классы Container, Iterable и Sized, а также определяет абстрактные методы __getitem__() и __len__(). Кроме того, предоставляет реализацию по умолчанию методов __contains__(), __iter__(), __reversed__(), index() и count(), которые реализованы исключительно посредством методов __get- get- item__()
и __len__().
MutableSequence
Базовый класс изменяемых последовательностей. Наследует класс Se- quence и добавляет абстрактные методы __setitem__() и __delitem__(). Кроме того, предоставляет реализацию по умолчанию методов append(), reverse(), extend()
, pop(), remove() и __iadd__().
Set
Базовый класс объектов, которые действуют как множества. Наследует классы Container, Iterable и Sized и определяет абстрактные методы __len__(),
__iter__() и __contains__(). Кроме того, предоставляет реализацию по умол- чанию операций над множествами __le__(), __lt__(), __eq__(), __ne__(),
__gt__()
, __ge__(), __and__(), __or__(), __xor__(), __sub__() и isdisjoint().
MutableSet
Базовый класс изменяемых множеств. Наследует класс Set и добавляет аб- страктные методы add() и discard(). Кроме того, предоставляет реализацию по умолчанию методов clear(), pop(), remove(), __ior__(), __iand__(), __ixor__
()
и __isub__().
Mapping
Базовый класс объектов, поддерживающих возможность отображения (сло- вари). Наследует классы Sized, Iterable и Container и определяет абстракт-

338
Глава 15. Структуры данных, алгоритмы и упрощение программного кода ные методы __getitem__(), __len__() и __iter__(). Предоставляет реализацию по умолчанию методов __contains__(), keys(), items(), values(), get(), __eq__() и __ne__().
MutableMapping
Базовый класс изменяемых объектов отображений. Наследует класс Map- ping и добавляет абстрактные методы __setitem__() и __delitem__(). Кроме того, предоставляет реализацию по умолчанию методов pop(), popitem(), clear()
, update() и setdefault().
MappingView
Базовый класс представлений отображений. Представление отображе- класс представлений отображений. Представление отображе- класс представлений отображений. Представление отображе- представлений отображений. Представление отображе- представлений отображений. Представление отображе- отображений. Представление отображе- отображений. Представление отображе-
. Представление отображе-
Представление отображе- ния – это объект, который позволяет обращаться к элементам объекта ото- бражения как к множествам. Например, представлением ключей является объект, напоминающий множество, который содержит ключи, имеющиеся в отображении. Подробнее об этом рассказывается в приложении A «Py-
A «Py-
«Py-
Py- thon 3».
KeysView
Базовый класс представления ключей отображения. Наследует классы
MappingView и Set.
ItemsView
Базовый класс представления элементов отображения. Наследует классы
MappingView и Set.
ValuesView
Базовый класс представления пар (key, item) отображения. Наследует классы MappingView и Set.
Соответствующие встроенные типы языка Python уже зарегистрированы в этих базовых классах. Кроме того, используя эти базовые классы, можно писать программы, которые выполняют более точную проверку типов. На- пример:
# Получить последний элемент последовательности if isinstance(x, collections.Sequence):
last = x[-1]
ёё
# Выполнить итерации по объекту, только если известен его размер if isinstance(x, collections.Iterable) and isinstance(x, collections.Sized):
for item in x:
инструкции
ёё
# Добавить новый элемент в множество if isinstance(x, collections.MutableSet):
x.add(item)
См. также
Глава 7 «Классы и объектно-ориентированное программирование».

Модуль contextlib
339
Модуль contextlib
М
одуль contextlib предоставляет декораторы и вспомогательные функции для создания менеджеров контекста, используемых совместно с инструк- цией with.
contextmanager(func)
Декоратор, который создает менеджер контекста из функции-генератора
func
. Декораторы используются, как показано ниже:
@contextmanager def foo(args):
statements try:
yield value except Exception as e:
error handling (if any)
инструкции
Когда интерпретатор встречает инструкцию with foo(args) as value, он вы- зывает функцию-генератор с указанными аргументами, которая выпол- няется до первой встреченной инструкции yield. Значение, возвращенное инструкцией yield, помещается в переменную value. После этого начина-
После этого начина- ется выполнение тела инструкции with. По завершении выполнения тела инструкции with возобновляется работа функции-генератора. Если внутри тела инструкции with возникнет какое-либо исключение, оно будет переда- но функции-генератору, где может быть обработано. Если ошибка не может быть обработана функцией-генератором, она должна повторно возбудить исключение. Пример использования декоратора можно найти в разделе
«Менеджеры контекста и инструкция with» в главе 5.
nested(mgr1, mgr2, ..., mgrN)
Функция, которая вызывает несколько менеджеров контекста mgr1, mgr2 и так далее, в виде единственной операции. Возвращает кортеж, содержа- щий различные возвращаемые значения инструкций with. Инструкция with nested(
m1,m2) as (x,y): инструкции
– это то же самое, что и инструкция with
m1 as x: with m2 as y: инструкции
. Следует заметить, что если во вложен- ном менеджере контекста будет перехвачено и обработано какое-либо ис- ключение, внешние менеджеры не получат об этом никакой информации.
closing(object)
Создает менеджер контекста, который автоматически вызовет метод ob-
ject.close()
по окончании выполнения тела инструкции with. Значением, возвращаемым инструкцией with, является сам объект object.
Модуль functools
Модуль functools содержит функции и декораторы, которые удобно исполь- зовать для создания высокоуровневых функций и декораторов в функцио- нальном программировании.

340
Глава 15. Структуры данных, алгоритмы и упрощение программного кода
1   ...   22   23   24   25   26   27   28   29   ...   82


написать администратору сайта