Документация Python неофициальный перевод

collections.md

1063 строк · 83.5 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3/library/collections.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `collections` – Типы данных-контейнеры89**Исходный код:** [Lib/collections/\_\_init\_\_.py](https://python-all.ru/src/3.14/Lib/collections/__init__.py)1011---1213Этот модуль предоставляет специализированные типы данных-контейнеры в качестве альтернативы встроенным контейнерам общего назначения Python: [`dict`](https://python-all.ru/3/library/stdtypes.html#dict), [`list`](https://python-all.ru/3/library/stdtypes.html#list), [`set`](https://python-all.ru/3/library/stdtypes.html#set) и [`tuple`](https://python-all.ru/3/library/stdtypes.html#tuple).1415| [`namedtuple()`](https://python-all.ru/3/library/collections.html#collections.namedtuple) | фабричная функция для создания подклассов кортежей с именованными полями |16| --- | --- |17| [`deque`](https://python-all.ru/3/library/collections.html#collections.deque) | контейнер, подобный списку, с быстрыми добавлением и извлечением с обоих концов |18| [`ChainMap`](https://python-all.ru/3/library/collections.html#collections.ChainMap) | класс, подобный словарю, для создания единого представления нескольких отображений |19| [`Counter`](https://python-all.ru/3/library/collections.html#collections.Counter) | подкласс dict для подсчёта [хешируемых](https://python-all.ru/3/glossary.html#term-hashable) объектов |20| [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) | подкласс dict, который запоминает порядок добавления записей |21| [`defaultdict`](https://python-all.ru/3/library/collections.html#collections.defaultdict) | подкласс dict, который вызывает фабричную функцию для предоставления отсутствующих значений |22| [`UserDict`](https://python-all.ru/3/library/collections.html#collections.UserDict) | обёртка вокруг словарей для упрощения создания подклассов dict |23| [`UserList`](https://python-all.ru/3/library/collections.html#collections.UserList) | обёртка вокруг списков для упрощения создания подклассов list |24| [`UserString`](https://python-all.ru/3/library/collections.html#collections.UserString) | обёртка вокруг строк для упрощения создания подклассов str |2526## [`ChainMap`](https://python-all.ru/3/library/collections.html#collections.ChainMap) объекты2728Добавлено в версии 3.3.2930Класс [`ChainMap`](https://python-all.ru/3/library/collections.html#collections.ChainMap) предназначен для быстрой связки нескольких отображений, чтобы их можно было рассматривать как единое целое. Часто он работает намного быстрее, чем создание нового словаря и выполнение нескольких вызовов [`update()`](https://python-all.ru/3/library/stdtypes.html#dict.update).3132Класс можно использовать для имитации вложенных областей видимости; он полезен в шаблонизаторах.3334#### `class collections.ChainMap(*maps)`3536`ChainMap` группирует несколько словарей или других отображений вместе, создавая единое обновляемое представление. Если не указаны *maps*, создаётся один пустой словарь, так что новая цепочка всегда содержит как минимум одно отображение.3738Базовые отображения хранятся в списке. Этот список является открытым; к нему можно обращаться или изменять его через атрибут *maps*. Других состояний нет.3940При поиске последовательно просматриваются базовые отображения, пока не будет найден ключ. В отличие от этого, записи, обновления и удаления работают только с первым отображением.4142`ChainMap` включает базовые отображения по ссылке. То есть, если одно из базовых отображений будет обновлено, эти изменения отразятся в `ChainMap`.4344Поддерживаются все обычные методы словаря. Кроме того, имеется атрибут *maps*, метод для создания новых подконтекстов и свойство для доступа ко всем отображениям, кроме первого:4546#### `maps`4748Обновляемый пользователем список отображений. Список упорядочен от первого просматриваемого к последнему. Это единственное сохраняемое состояние, и его можно изменять, чтобы менять порядок поиска отображений. Список всегда должен содержать хотя бы одно отображение.4950#### `new_child(m=None, **kwargs)`5152Возвращает новый `ChainMap`, содержащий новое отображение, за которым следуют все отображения из текущего экземпляра. Если указан `m`, он становится новым отображением в начале списка отображений; если не указан, используется пустой словарь, так что вызов `d.new_child()` эквивалентен: `ChainMap({}, *d.maps)`. Если указаны какие-либо именованные аргументы, они обновляют переданное отображение или новый пустой словарь. Этот метод используется для создания подконтекстов, которые можно обновлять, не изменяя значения в родительских отображениях.5354Изменено в версии 3.4: Был добавлен необязательный параметр `m`.5556Изменено в версии 3.10: Добавлена поддержка именованных аргументов.5758#### `parents`5960Свойство, возвращающее новый `ChainMap`, содержащий все отображения из текущего экземпляра, кроме первого. Это полезно для пропуска первого отображения при поиске. Варианты использования аналогичны ключевому слову [`nonlocal`](https://python-all.ru/3/reference/simple_stmts.html#nonlocal), применяемому в [вложенных областях видимости](https://python-all.ru/3/glossary.html#term-nested-scope). Также они параллельны встроенной функции [`super()`](https://python-all.ru/3/library/functions.html#super). Ссылка на `d.parents` эквивалентна: `ChainMap(*d.maps[1:])`.6162Обратите внимание, порядок итерации `ChainMap` определяется сканированием отображений от последнего к первому:6364```python65>>> baseline = {'music': 'bach', 'art': 'rembrandt'}66>>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}67>>> list(ChainMap(adjustments, baseline))68['music', 'art', 'opera']69```7071Это даёт тот же порядок, что и серия вызовов [`dict.update()`](https://python-all.ru/3/library/stdtypes.html#dict.update), начиная с последнего отображения:7273```python74>>> combined = baseline.copy()75>>> combined.update(adjustments)76>>> list(combined)77['music', 'art', 'opera']78```7980Changed in version 3.9: Added support for `|` and `|=` operators, specified in [**PEP 584**](https://python-all.ru/3/library/collections.html).8182> **См. также**83>84> - Класс [MultiContext](https://python-all.ru/3/library/collections.html) в пакете Enthought [CodeTools](https://python-all.ru/3/library/collections.html) имеет опции для поддержки записи в любое отображение в цепочке.85> - Класс [Context](https://python-all.ru/3/library/collections.html) в Django для шаблонов представляет собой цепочку отображений только для чтения. Он также поддерживает добавление и удаление контекстов, аналогично методу [`new_child()`](https://python-all.ru/3/library/collections.html#collections.ChainMap.new_child) и свойству [`parents`](https://python-all.ru/3/library/collections.html#collections.ChainMap.parents).86> - Рецепт [Nested Contexts](https://python-all.ru/3/library/collections.html) содержит опции для управления тем, применяются ли записи и другие изменения только к первому отображению или к любому отображению в цепочке.87> - [Сильно упрощённая версия Chainmap только для чтения](https://python-all.ru/3/library/collections.html).8889### [`ChainMap`](https://python-all.ru/3/library/collections.html#collections.ChainMap) Примеры и рецепты9091В этом разделе показаны различные подходы к работе с цепочечными отображениями.9293Пример симуляции внутренней цепочки поиска Python:9495```python96import builtins97pylookup = ChainMap(locals(), globals(), vars(builtins))98```99100Пример, когда заданные пользователем аргументы командной строки имеют приоритет над переменными окружения, которые, в свою очередь, имеют приоритет над значениями по умолчанию:101102```python103import os, argparse104105defaults = {'color': 'red', 'user': 'guest'}106107parser = argparse.ArgumentParser()108parser.add_argument('-u', '--user')109parser.add_argument('-c', '--color')110namespace = parser.parse_args()111command_line_args = {k: v for k, v in vars(namespace).items() if v is not None}112113combined = ChainMap(command_line_args, os.environ, defaults)114print(combined['color'])115print(combined['user'])116```117118Примеры шаблонов использования класса [`ChainMap`](https://python-all.ru/3/library/collections.html#collections.ChainMap) для симуляции вложенных контекстов:119120```python121c = ChainMap()        # Создать корневой контекст122d = c.new_child()     # Создать вложенный дочерний контекст123e = c.new_child()     # Дочерний контекст c, независимый от d124e.maps[0]             # Словарь текущего контекста – как locals() в Python125e.maps[-1]            # Корневой контекст – как globals() в Python126e.parents             # Цепочка объемлющих контекстов – как nonlocals в Python127128d['x'] = 1            # Установить значение в текущем контексте129d['x']                # Получить первый ключ в цепочке контекстов130del d['x']            # Удалить из текущего контекста131list(d)               # Все вложенные значения132k in d                # Проверить все вложенные значения133len(d)                # Количество вложенных значений134d.items()             # Все вложенные элементы135dict(d)               # Развернуть в обычный словарь136```137138Класс [`ChainMap`](https://python-all.ru/3/library/collections.html#collections.ChainMap) выполняет обновления (запись и удаление) только в первом отображении цепочки, в то время как поиск просматривает всю цепочку. Однако, если требуется глубокая запись и удаление, легко создать подкласс, который обновляет ключи, найденные глубже в цепочке:139140```python141class DeepChainMap(ChainMap):142    'Variant of ChainMap that allows direct updates to inner scopes'143144    def __setitem__(self, key, value):145        for mapping in self.maps:146            if key in mapping:147                mapping[key] = value148                return149        self.maps[0][key] = value150151    def __delitem__(self, key):152        for mapping in self.maps:153            if key in mapping:154                del mapping[key]155                return156        raise KeyError(key)157158>>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})159>>> d['lion'] = 'orange'         # обновить существующий ключ на два уровня ниже160>>> d['snake'] = 'red'           # новые ключи добавляются в самый верхний словарь161>>> del d['elephant']            # удалить существующий ключ на один уровень ниже162>>> d                            # отобразить результат163DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})164```165166## [`Counter`](https://python-all.ru/3/library/collections.html#collections.Counter) Объекты167168Предоставляется инструмент счётчика для удобного и быстрого подсчёта. Например:169170```python171>>> # Подсчитать вхождения слов в списке172>>> cnt = Counter()173>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:174...     cnt[word] += 1175...176>>> cnt177Counter({'blue': 3, 'red': 2, 'green': 1})178179>>> # Найти десять самых распространённых слов в «Гамлете»180>>> import re181>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())182>>> Counter(words).most_common(10)183[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),184 ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]185```186187#### `class collections.Counter(**kwargs)`188189#### `class collections.Counter(iterable, /, **kwargs)`190191#### `class collections.Counter(mapping, /, **kwargs)`192193`Counter` – это подкласс [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) для подсчёта [хешируемых](https://python-all.ru/3/glossary.html#term-hashable) объектов. Это коллекция, в которой элементы хранятся как ключи словаря, а их количества – как значения словаря. Количествами могут быть любые целые числа, включая ноль или отрицательные. Класс `Counter` аналогичен мешкам (bags) или мультимножествам в других языках.194195Элементы подсчитываются из *итерируемого объекта* или инициализируются из другого *отображения* (или счётчика):196197```python198>>> c = Counter()                           # новый пустой счётчик199>>> c = Counter('gallahad')                 # новый счётчик из итерируемого объекта200>>> c = Counter({'red': 4, 'blue': 2})      # новый счётчик из отображения201>>> c = Counter(cats=4, dogs=8)             # новый счётчик из именованных аргументов202```203204Объекты Counter имеют интерфейс словаря, за исключением того, что они возвращают ноль для отсутствующих элементов вместо возбуждения [`KeyError`](https://python-all.ru/3/library/exceptions.html#KeyError):205206```python207>>> c = Counter(['eggs', 'ham'])208>>> c['bacon']                              # счёт отсутствующего элемента равен нулю2090210```211212Установка количества в ноль не удаляет элемент из счётчика. Используйте `del` для полного удаления:213214```python215>>> c['sausage'] = 0                        # запись счётчика с нулевым значением216>>> del c['sausage']                        # del действительно удаляет запись217```218219Добавлено в версии 3.1.220221Изменено в версии 3.7: Будучи подклассом [`dict`](https://python-all.ru/3/library/stdtypes.html#dict), `Counter` унаследовал возможность запоминать порядок вставки. Математические операции над объектами *Counter* также сохраняют порядок. Результаты упорядочиваются согласно времени первого появления элемента в левом операнде, а затем по порядку появления в правом операнде.222223Объекты Counter поддерживают дополнительные методы помимо тех, что доступны для всех словарей:224225#### `elements()`226227Возвращает итератор по элементам, повторяя каждый столько раз, сколько указано в его количестве. Элементы возвращаются в порядке первого появления. Если количество элемента меньше единицы, `elements()` игнорирует его.228229```python230>>> c = Counter(a=4, b=2, c=0, d=-2)231>>> sorted(c.elements())232['a', 'a', 'a', 'a', 'b', 'b']233```234235#### `most_common(n=None)`236237Возвращает список из *n* наиболее часто встречающихся элементов и их количества от самого частого к наименее частому. Если *n* опущено или `None`, `most_common()` возвращает *все* элементы счётчика. Элементы с одинаковым количеством упорядочиваются в порядке первого появления:238239```python240>>> Counter('abracadabra').most_common(3)241[('a', 5), ('b', 2), ('r', 2)]242```243244#### `subtract(**kwargs)`245246#### `subtract(iterable, /, **kwargs)`247248#### `subtract(mapping, /, **kwargs)`249250Элементы вычитаются из *итерируемого объекта* или из другого *отображения* (или счётчика). Подобно [`dict.update()`](https://python-all.ru/3/library/stdtypes.html#dict.update), но вычитает количества вместо замены. Как входные, так и выходные значения могут быть нулевыми или отрицательными.251252```python253>>> c = Counter(a=4, b=2, c=0, d=-2)254>>> d = Counter(a=1, b=2, c=3, d=4)255>>> c.subtract(d)256>>> c257Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})258```259260Добавлено в версии 3.2.261262#### `total()`263264Вычисляет сумму количеств.265266```python267>>> c = Counter(a=10, b=5, c=0)268>>> c.total()26915270```271272Добавлено в версии 3.10.273274Обычные методы словарей доступны для объектов `Counter`, за исключением двух, которые работают с счётчиками иначе.275276#### `fromkeys(iterable)`277278Этот метод класса не реализован для объектов `Counter`.279280#### `update(**kwargs)`281282#### `update(iterable, /, **kwargs)`283284#### `update(mapping, /, **kwargs)`285286Элементы подсчитываются из *итерируемого объекта* или добавляются из другого *отображения* (или счётчика). Как и [`dict.update()`](https://python-all.ru/3/library/stdtypes.html#dict.update), но увеличивает счётчики вместо их замены. Кроме того, *итерируемый объект* должен быть последовательностью элементов, а не последовательностью `(key, value)` пар.287288Счётчики поддерживают операторы расширенного сравнения для отношений равенства, подмножества и надмножества: `==`, `!=`, `<`, `<=`, `>`, `>=`. Все эти проверки считают отсутствующие элементы имеющими нулевые счётчики, так что `Counter(a=1) == Counter(a=1, b=0)` возвращает истину.289290Изменено в версии 3.10: Добавлены операции расширенного сравнения.291292Изменено в версии 3.10: При проверке на равенство отсутствующие элементы считаются имеющими нулевые счётчики. Ранее `Counter(a=3)` и `Counter(a=3, b=0)` считались различными.293294Типичные приёмы работы с объектами [`Counter`](https://python-all.ru/3/library/collections.html#collections.Counter):295296```python297c.total()                       # сумма всех значений298c.clear()                       # сбросить все значения299list(c)                         # список уникальных элементов300set(c)                          # преобразовать в множество301dict(c)                         # преобразовать в обычный словарь302c.items()                       # доступ к парам (элемент, кол-во)303Counter(dict(list_of_pairs))    # создать из списка пар (элемент, кол-во)304c.most_common()[:-n-1:-1]       # n наименее частых элементов305+c                              # удалить нулевые и отрицательные значения306```307308Для объединения объектов [`Counter`](https://python-all.ru/3/library/collections.html#collections.Counter) в мультимножества (счётчики, у которых счётчики больше нуля) предоставляется несколько математических операций. Сложение и вычитание объединяют счётчики, складывая или вычитая счётчики соответствующих элементов. Пересечение и объединение возвращают минимум и максимум соответствующих счётчиков. Равенство и включение сравнивают соответствующие счётчики. Каждая операция может принимать входные данные со знаковыми счётчиками, но из результата исключаются значения со счётчиками, равными нулю или меньше.309310```pycon311>>> c = Counter(a=3, b=1)312>>> d = Counter(a=1, b=2)313>>> c + d                       # сложение двух счётчиков: c[x] + d[x]314Counter({'a': 4, 'b': 3})315>>> c - d                       # вычитание (остаются только положительные значения)316Counter({'a': 2})317>>> c & d                       # пересечение: min(c[x], d[x])318Counter({'a': 1, 'b': 1})319>>> c | d                       # объединение: max(c[x], d[x])320Counter({'a': 3, 'b': 2})321>>> c == d                      # равенство: c[x] == d[x]322False323>>> c <= d                      # включение: c[x] <= d[x]324False325```326327Унарное сложение и вычитание – это сокращения для добавления пустого счётчика или вычитания из пустого счётчика.328329```python330>>> c = Counter(a=2, b=-4)331>>> +c332Counter({'a': 2})333>>> -c334Counter({'b': 4})335```336337Добавлено в версии 3.3: Добавлена поддержка унарного плюса, унарного минуса и операций над мультимножествами на месте.338339> **Примечание**340>341> Счётчики в первую очередь предназначены для работы с положительными целыми числами для представления текущих счётчиков; однако была предпринята осторожность, чтобы излишне не исключать варианты использования, требующие других типов или отрицательных значений. Чтобы помочь с такими вариантами, в этом разделе описаны минимальные ограничения по диапазону и типам.342>343> - Сам класс [`Counter`](https://python-all.ru/3/library/collections.html#collections.Counter) является подклассом словаря без ограничений на ключи и значения. Значения должны быть числами, представляющими счётчики, но в поле значения *можно* хранить что угодно.344> - Метод [`most_common()`](https://python-all.ru/3/library/collections.html#collections.Counter.most_common) требует только упорядочиваемости значений.345> - Для операций на месте, таких как `c[key] += 1`, тип значения должен поддерживать только сложение и вычитание. Так что дроби, числа с плавающей запятой и десятичные числа будут работать, и отрицательные значения поддерживаются. То же самое верно для [`update()`](https://python-all.ru/3/library/collections.html#collections.Counter.update) и [`subtract()`](https://python-all.ru/3/library/collections.html#collections.Counter.subtract), которые допускают отрицательные и нулевые значения как для входных, так и для выходных данных.346> - Методы мультимножеств предназначены только для случаев использования с положительными значениями. Входные данные могут быть отрицательными или нулевыми, но создаются только выходные данные с положительными значениями. Ограничений на тип нет, но тип значения должен поддерживать сложение, вычитание и сравнение.347> - Метод [`elements()`](https://python-all.ru/3/library/collections.html#collections.Counter.elements) требует целочисленных счётчиков. Он игнорирует нулевые и отрицательные счётчики.348349> **См. также**350>351> - [Класс Bag](https://python-all.ru/3/library/collections.html) в Smalltalk.352> - Статья в Википедии о [мультимножествах](https://python-all.ru/3/library/collections.html).353> - [Мультимножества в C++](https://python-all.ru/3/library/collections.html): учебное пособие с примерами.354> - О математических операциях над мультимножествами и их применении см. *Кнут, Дональд. Искусство программирования, том II, раздел 4.6.3, упражнение 19*.355> - Для перечисления всех различных мультимножеств заданного размера над заданным набором элементов см. [`itertools.combinations_with_replacement()`](https://python-all.ru/3/library/itertools.html#itertools.combinations_with_replacement):356>357>   ```python358>   map(Counter, combinations_with_replacement('ABC', 2)) # --> AA AB AC BB BC CC359>   ```360361## [`deque`](https://python-all.ru/3/library/collections.html#collections.deque) объекты362363#### `class collections.deque([iterable[, maxlen]])`364365Возвращает новый объект deque, инициализированный слева направо (с помощью [`append()`](https://python-all.ru/3/library/collections.html#collections.deque.append)) данными из *итерируемого объекта*. Если *итерируемый объект* не указан, новый deque пуст.366367Deque – это обобщение стеков и очередей (название произносится как «дек» и является сокращением от «double-ended queue» – двусторонняя очередь). Deque поддерживают потокобезопасные и эффективные по памяти добавления и удаления с любого конца с примерно одинаковой производительностью *O*(1) в обоих направлениях.368369Хотя объекты [`list`](https://python-all.ru/3/library/stdtypes.html#list) поддерживают похожие операции, они оптимизированы для быстрых операций фиксированной длины и несут затраты на перемещение памяти *O*(*n*) для операций `pop(0)` и `insert(0, v)`, которые изменяют как размер, так и положение базового представления данных.370371Если *maxlen* не указан или равен `None`, deques могут расти до произвольной длины. В противном случае deque ограничен заданной максимальной длиной. Как только deque ограниченной длины заполняется, при добавлении новых элементов соответствующее количество элементов отбрасывается с противоположного конца. Deque с ограниченной длиной предоставляют функциональность, аналогичную фильтру `tail` в Unix. Они также полезны для отслеживания транзакций и других пулов данных, где интерес представляет только самая последняя активность.372373Объекты deque являются [обобщёнными](https://python-all.ru/3/library/typing.html#generics) по типу своего содержимого.374375Объекты deque поддерживают следующие методы:376377#### `append(item, /)`378379Добавляет *элемент* в правую часть deque.380381#### `appendleft(item, /)`382383Добавляет *элемент* в левую часть deque.384385#### `clear()`386387Удаляет все элементы из deque, после чего его длина равна 0.388389#### `copy()`390391Создаёт поверхностную копию deque.392393Добавлено в версии 3.5.394395#### `count(value, /)`396397Подсчитывает количество элементов deque, равных *значению*.398399Добавлено в версии 3.2.400401#### `extend(iterable, /)`402403Расширяет правую часть deque, добавляя элементы из итерируемого объекта.404405#### `extendleft(iterable, /)`406407Расширяет левую часть deque, добавляя элементы из *итерируемого объекта*. Обратите внимание: последовательное добавление слева приводит к обращению порядка элементов в итерируемом объекте.408409#### `index(value[, start[, stop]])`410411Возвращает позицию *значения* в deque (начиная с индекса *start* и до индекса *stop*). Возвращает первое совпадение или вызывает исключение [`ValueError`](https://python-all.ru/3/library/exceptions.html#ValueError), если не найдено.412413Добавлено в версии 3.5.414415#### `insert(index, value, /)`416417Вставляет *значение* в deque на позицию *индекс*.418419Если вставка приведёт к тому, что ограниченный deque превысит *maxlen*, вызывается исключение [`IndexError`](https://python-all.ru/3/library/exceptions.html#IndexError).420421Добавлено в версии 3.5.422423#### `pop()`424425Удаляет и возвращает элемент из правой части deque. Если элемент отсутствует, вызывает исключение [`IndexError`](https://python-all.ru/3/library/exceptions.html#IndexError).426427#### `popleft()`428429Удаляет и возвращает элемент из левой части deque. Если элемент отсутствует, вызывает исключение [`IndexError`](https://python-all.ru/3/library/exceptions.html#IndexError).430431#### `remove(value, /)`432433Удаляет первое вхождение *значения*. Если не найдено, вызывает исключение [`ValueError`](https://python-all.ru/3/library/exceptions.html#ValueError).434435#### `reverse()`436437Переворачивает элементы deque на месте и возвращает `None`.438439Добавлено в версии 3.2.440441#### `rotate(n=1, /)`442443Поворачивает deque на *n* шагов вправо. Если *n* отрицательное, поворачивает влево.444445Когда deque не пуст, поворот на один шаг вправо эквивалентен `d.appendleft(d.pop())`, а поворот на один шаг влево – `d.append(d.popleft())`.446447Объекты deque также предоставляют один атрибут только для чтения:448449#### `maxlen`450451Максимальный размер дека или `None`, если неограничен.452453Добавлено в версии 3.1.454455В дополнение к вышесказанному, деки поддерживают итерацию, pickling, `len(d)`, `reversed(d)`, `copy.copy(d)`, `copy.deepcopy(d)`, проверку принадлежности с помощью оператора [`in`](https://python-all.ru/3/reference/expressions.html#in) и обращение по индексу, например `d[0]` для доступа к первому элементу. Доступ по индексу выполняется за *O*(1) на обоих концах, но замедляется до *O*(*n*) в середине. Для быстрого произвольного доступа лучше использовать списки.456457Начиная с версии 3.5, деки поддерживают `__add__()`, `__mul__()` и `__imul__()`.458459Пример:460461```pycon462>>> from collections import deque463>>> d = deque('ghi')                 # создать новый deque с тремя элементами464>>> for elem in d:                   # обход элементов deque465...     print(elem.upper())466G467H468I469470>>> d.append('j')                    # добавить новый элемент справа471>>> d.appendleft('f')                # добавить новый элемент слева472>>> d                                # показать представление deque473deque(['f', 'g', 'h', 'i', 'j'])474475>>> d.pop()                          # вернуть и удалить правый элемент476'j'477>>> d.popleft()                      # вернуть и удалить левый элемент478'f'479>>> list(d)                          # вывести содержимое deque480['g', 'h', 'i']481>>> d[0]                             # посмотреть левый элемент482'g'483>>> d[-1]                            # посмотреть правый элемент484'i'485486>>> list(reversed(d))                # вывести содержимое deque в обратном порядке487['i', 'h', 'g']488>>> 'h' in d                         # поиск в deque489True490>>> d.extend('jkl')                  # добавить несколько элементов за раз491>>> d492deque(['g', 'h', 'i', 'j', 'k', 'l'])493>>> d.rotate(1)                      # поворот вправо494>>> d495deque(['l', 'g', 'h', 'i', 'j', 'k'])496>>> d.rotate(-1)                     # поворот влево497>>> d498deque(['g', 'h', 'i', 'j', 'k', 'l'])499500>>> deque(reversed(d))               # создать новую deque в обратном порядке501deque(['l', 'k', 'j', 'i', 'h', 'g'])502>>> d.clear()                        # очистить deque503>>> d.pop()                          # невозможно извлечь элемент из пустой deque504Traceback (most recent call last):505    File "<pyshell#6>", line 1, in -toplevel-506        d.pop()507IndexError: pop from an empty deque508509>>> d.extendleft('abc')              # extendleft() меняет порядок ввода на обратный510>>> d511deque(['c', 'b', 'a'])512```513514### [`deque`](https://python-all.ru/3/library/collections.html#collections.deque) Рецепты515516В этом разделе рассматриваются различные подходы к работе с деками.517518Деки с ограниченной длиной предоставляют функциональность, аналогичную фильтру `tail` в Unix:519520```python521def tail(filename, n=10):522    'Return the last n lines of a file'523    with open(filename) as f:524        return deque(f, n)525```526527Другой подход к использованию деков заключается в поддержании последовательности недавно добавленных элементов путем добавления справа и извлечения слева:528529```python530def moving_average(iterable, n=3):531    # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0532    # https://en.wikipedia.org/wiki/Moving_average533    it = iter(iterable)534    d = deque(itertools.islice(it, n-1))535    d.appendleft(0)536    s = sum(d)537    for elem in it:538        s += elem - d.popleft()539        d.append(elem)540        yield s / n541```542543[Планировщик round-robin](https://python-all.ru/3/library/collections.html) можно реализовать с помощью входных итераторов, хранящихся в [`deque`](https://python-all.ru/3/library/collections.html#collections.deque). Значения выдаются из активного итератора в позиции ноль. Если этот итератор исчерпан, его можно удалить с помощью [`popleft()`](https://python-all.ru/3/library/collections.html#collections.deque.popleft); в противном случае его можно вернуть в конец с помощью метода [`rotate()`](https://python-all.ru/3/library/collections.html#collections.deque.rotate):544545```python546def roundrobin(*iterables):547    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"548    iterators = deque(map(iter, iterables))549    while iterators:550        try:551            while True:552                yield next(iterators[0])553                iterators.rotate(-1)554        except StopIteration:555            # Удалить исчерпанный итератор.556            iterators.popleft()557```558559Метод [`rotate()`](https://python-all.ru/3/library/collections.html#collections.deque.rotate) позволяет реализовать [`deque`](https://python-all.ru/3/library/collections.html#collections.deque) срезы и удаление. Например, чистая реализация `del d[n]` на Python использует метод `rotate()` для позиционирования элементов, которые нужно извлечь:560561```python562def delete_nth(d, n):563    d.rotate(-n)564    d.popleft()565    d.rotate(n)566```567568To implement [`deque`](https://python-all.ru/3/library/collections.html#collections.deque) slicing, use a similar approach applying [`rotate()`](https://python-all.ru/3/library/collections.html#collections.deque.rotate) to bring a target element to the left side of the deque. Remove old entries with [`popleft()`](https://python-all.ru/3/library/collections.html#collections.deque.popleft), add new entries with [`extend()`](https://python-all.ru/3/library/collections.html#collections.deque.extend), and then reverse the rotation. With minor variations on that approach, it is easy to implement Forth style stack manipulations such as `dup`, `drop`, `swap`, `over`, `pick`, `rot`, and `roll`.569570## [`defaultdict`](https://python-all.ru/3/library/collections.html#collections.defaultdict) Объекты571572#### `class collections.defaultdict(default_factory=None, /, **kwargs)`573574#### `class collections.defaultdict(default_factory, mapping, /, **kwargs)`575576#### `class collections.defaultdict(default_factory, iterable, /, **kwargs)`577578Возвращает новый объект, подобный словарю. `defaultdict` является подклассом встроенного класса [`dict`](https://python-all.ru/3/library/stdtypes.html#dict). Он переопределяет один метод и добавляет одну изменяемую переменную экземпляра. Остальная функциональность такая же, как у класса `dict`, и не документируется здесь.579580Первый аргумент задает начальное значение для атрибута [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory); по умолчанию он равен `None`. Все остальные аргументы обрабатываются так же, как если бы они были переданы конструктору [`dict`](https://python-all.ru/3/library/stdtypes.html#dict), включая именованные аргументы.581582`defaultdict` являются [обобщенными](https://python-all.ru/3/library/typing.html#generics) по двум типам, обозначающим (соответственно) типы ключей и значений словаря.583584`defaultdict` объекты поддерживают следующий метод в дополнение к стандартным операциям [`dict`](https://python-all.ru/3/library/stdtypes.html#dict):585586#### `__missing__(key, /)`587588Если атрибут [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory) равен `None`, возникает исключение [`KeyError`](https://python-all.ru/3/library/exceptions.html#KeyError) с аргументом *key*.589590Если [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory) не равен `None`, он вызывается без аргументов для предоставления значения по умолчанию для заданного *key*; это значение вставляется в словарь для *key* и возвращается.591592Если вызов [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory) вызывает исключение, это исключение распространяется без изменений.593594Этот метод вызывается методом [`__getitem__()`](https://python-all.ru/3/reference/datamodel.html#object.__getitem__) класса [`dict`](https://python-all.ru/3/library/stdtypes.html#dict), когда запрошенный ключ не найден; все, что он возвращает или возбуждает, затем возвращается или возбуждается методом `__getitem__()`.595596Обратите внимание, что `__missing__()` *не* вызывается для любых операций, кроме [`__getitem__()`](https://python-all.ru/3/reference/datamodel.html#object.__getitem__). Это означает, что [`get()`](https://python-all.ru/3/library/stdtypes.html#dict.get), как и обычные словари, будет возвращать `None` по умолчанию, а не использовать [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory).597598`defaultdict` объекты поддерживают следующую переменную экземпляра:599600#### `default_factory`601602Этот атрибут используется методом [`__missing__()`](https://python-all.ru/3/library/collections.html#collections.defaultdict.__missing__); он инициализируется из первого аргумента конструктора, если он присутствует, или `None`, если отсутствует.603604Изменено в версии 3.9: Добавлены операторы слияния (`|`) и обновления (`|=`), указанные в [**PEP 584**](https://python-all.ru/3/library/collections.html).605606### [`defaultdict`](https://python-all.ru/3/library/collections.html#collections.defaultdict) Примеры607608Используя [`list`](https://python-all.ru/3/library/stdtypes.html#list) в качестве [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory), легко сгруппировать последовательность пар ключ-значение в словарь списков:609610```python611>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]612>>> d = defaultdict(list)613>>> for k, v in s:614...     d[k].append(v)615...616>>> sorted(d.items())617[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]618```619620Когда ключ встречается впервые, его еще нет в отображении; поэтому запись автоматически создается с помощью функции [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory), которая возвращает пустой [`list`](https://python-all.ru/3/library/stdtypes.html#list). Затем операция [`list.append()`](https://python-all.ru/3/library/stdtypes.html#list.append) присоединяет значение к новому списку. Когда ключи встречаются снова, поиск выполняется обычным образом (возвращается список для этого ключа), и операция `list.append()` добавляет еще одно значение в список. Этот метод проще и быстрее, чем эквивалентный метод с использованием [`dict.setdefault()`](https://python-all.ru/3/library/stdtypes.html#dict.setdefault):621622```python623>>> d = {}624>>> for k, v in s:625...     d.setdefault(k, []).append(v)626...627>>> sorted(d.items())628[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]629```630631Установка [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory) в [`int`](https://python-all.ru/3/library/functions.html#int) делает [`defaultdict`](https://python-all.ru/3/library/collections.html#collections.defaultdict) удобным для подсчёта (как bag или мультимножество в других языках):632633```python634>>> s = 'mississippi'635>>> d = defaultdict(int)636>>> for k in s:637...     d[k] += 1638...639>>> sorted(d.items())640[('i', 4), ('m', 1), ('p', 2), ('s', 4)]641```642643Когда буква встречается впервые, в отображении она отсутствует, поэтому функция [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory) вызывает [`int()`](https://python-all.ru/3/library/functions.html#int) для получения нулевого значения по умолчанию. Затем операция инкремента наращивает счётчик для каждой буквы.644645Функция [`int()`](https://python-all.ru/3/library/functions.html#int), всегда возвращающая ноль, – это всего лишь частный случай константных функций. Более быстрый и гибкий способ создания константных функций – использовать лямбда-функцию, которая может возвращать любое константное значение (не только ноль):646647```python648>>> def constant_factory(value):649...     return lambda: value650...651>>> d = defaultdict(constant_factory('<missing>'))652>>> d.update(name='John', action='ran')653>>> '%(name)s %(action)s to %(object)s' % d654'John ran to <missing>'655```656657Установка [`default_factory`](https://python-all.ru/3/library/collections.html#collections.defaultdict.default_factory) в [`set`](https://python-all.ru/3/library/stdtypes.html#set) делает [`defaultdict`](https://python-all.ru/3/library/collections.html#collections.defaultdict) удобным для построения словаря множеств:658659```python660>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]661>>> d = defaultdict(set)662>>> for k, v in s:663...     d[k].add(v)664...665>>> sorted(d.items())666[('blue', {2, 4}), ('red', {1, 3})]667```668669## [`namedtuple()`](https://python-all.ru/3/library/collections.html#collections.namedtuple) Фабричная функция для кортежей с именованными полями670671Именованные кортежи придают смысл каждой позиции в кортеже и позволяют писать более читаемый, самодокументируемый код. Их можно использовать везде, где используются обычные кортежи, и они добавляют возможность доступа к полям по имени, а не по индексу.672673#### `collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)`674675Возвращает новый подкласс кортежа с именем *typename*. Этот подкласс используется для создания объектов, похожих на кортежи, поля которых доступны через атрибуты, а также их можно индексировать и итерировать. Экземпляры подкласса также имеют полезную строку документации (с *typename* и *field\_names*) и полезный метод [`__repr__()`](https://python-all.ru/3/reference/datamodel.html#object.__repr__), который выводит содержимое кортежа в формате `name=value`.676677Параметр *field\_names* представляет собой последовательность строк, например `['x', 'y']`. В качестве альтернативы *field\_names* может быть единой строкой, в которой имена полей разделены пробелами и/или запятыми, например `'x y'` или `'x, y'`.678679В качестве имени поля может использоваться любой допустимый идентификатор Python, кроме имён, начинающихся с подчёркивания. Допустимые идентификаторы состоят из букв, цифр и символов подчёркивания, но не начинаются с цифры или подчёркивания и не могут быть [`keyword`](https://python-all.ru/3/library/keyword.html#module-keyword), например *class*, *for*, *return*, *global*, *pass*, или *raise*.680681Если *rename* равен true, недопустимые имена полей автоматически заменяются позиционными именами. Например, `['abc', 'def', 'ghi', 'abc']` преобразуется в `['abc', '_1', 'ghi', '_3']`, устраняя ключевое слово `def` и дублирующееся имя поля `abc`.682683Параметр *defaults* может быть `None` или [итерируемым объектом](https://python-all.ru/3/glossary.html#term-iterable) значений по умолчанию. Поскольку поля со значением по умолчанию должны идти после полей без умолчания, *defaults* применяются к самым правым параметрам. Например, если имена полей `['x', 'y', 'z']`, а значения по умолчанию – `(1, 2)`, то `x` будет обязательным аргументом, `y` по умолчанию будет равно `1`, а `z``2`.684685Если задан параметр *module*, то атрибут [`__module__`](https://python-all.ru/3/reference/datamodel.html#type.__module__) именованного кортежа устанавливается в это значение.686687Экземпляры именованных кортежей не имеют собственных словарей, поэтому они легковесны и потребляют не больше памяти, чем обычные кортежи.688689Для поддержки сериализации (pickle) класс именованного кортежа должен быть присвоен переменной, соответствующей *typename*.690691Изменено в версии 3.1: Добавлена поддержка *rename*.692693Изменено в версии 3.6: Параметры *verbose* и *rename* стали [только именованными аргументами](https://python-all.ru/3/glossary.html#keyword-only-parameter).694695Изменено в версии 3.6: Добавлен параметр *module*.696697Изменено в версии 3.7: Удалены параметр *verbose* и атрибут `_source`.698699Изменено в версии 3.7: Добавлены параметр *defaults* и атрибут [`_field_defaults`](https://python-all.ru/3/library/collections.html#collections.somenamedtuple._field_defaults).700701```pycon702>>> # Базовый пример703>>> Point = namedtuple('Point', ['x', 'y'])704>>> p = Point(11, y=22)     # создать экземпляр с позиционными или именованными аргументами705>>> p[0] + p[1]             # доступен по индексу, как обычный кортеж (11, 22)70633707>>> x, y = p                # распаковывается как обычный кортеж708>>> x, y709(11, 22)710>>> p.x + p.y               # поля также доступны по имени71133712>>> p                       # читаемое __repr__ в стиле name=value713Point(x=11, y=22)714```715716Именованные кортежи особенно полезны для присваивания имён полей кортежам результатов, возвращаемых модулями [`csv`](https://python-all.ru/3/library/csv.html#module-csv) или [`sqlite3`](https://python-all.ru/3/library/sqlite3.html#module-sqlite3):717718```python719EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')720721import csv722for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):723    print(emp.name, emp.title)724725import sqlite3726conn = sqlite3.connect('/companydata')727cursor = conn.cursor()728cursor.execute('SELECT name, age, title, department, paygrade FROM employees')729for emp in map(EmployeeRecord._make, cursor.fetchall()):730    print(emp.name, emp.title)731```732733В дополнение к методам, унаследованным от кортежей, именованные кортежи поддерживают три дополнительных метода и два атрибута. Чтобы избежать конфликтов с именами полей, имена методов и атрибутов начинаются с подчёркивания.734735#### `classmethod somenamedtuple._make(iterable, /)`736737Метод класса, который создаёт новый экземпляр из существующей последовательности или итерируемого объекта.738739```pycon740>>> t = [11, 22]741>>> Point._make(t)742Point(x=11, y=22)743```744745#### `somenamedtuple._asdict()`746747Возвращает новый [`dict`](https://python-all.ru/3/library/stdtypes.html#dict), который отображает имена полей в соответствующие значения:748749```pycon750>>> p = Point(x=11, y=22)751>>> p._asdict()752{'x': 11, 'y': 22}753```754755Изменено в версии 3.1: Возвращает [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) вместо обычного [`dict`](https://python-all.ru/3/library/stdtypes.html#dict).756757Изменено в версии 3.8: Возвращает обычный [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) вместо [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict). Начиная с Python 3.7, обычные словари гарантированно упорядочены. Если требуются дополнительные возможности `OrderedDict`, рекомендуется преобразовать результат к нужному типу: `OrderedDict(nt._asdict())`.758759#### `somenamedtuple._replace(**kwargs)`760761Возвращает новый экземпляр именованного кортежа, заменяя указанные поля новыми значениями:762763```python764>>> p = Point(x=11, y=22)765>>> p._replace(x=33)766Point(x=33, y=22)767768>>> for partnum, record in inventory.items():769...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())770```771772Именованные кортежи также поддерживаются обобщённой функцией [`copy.replace()`](https://python-all.ru/3/library/copy.html#copy.replace).773774Изменено в версии 3.13: Возбуждается [`TypeError`](https://python-all.ru/3/library/exceptions.html#TypeError) вместо [`ValueError`](https://python-all.ru/3/library/exceptions.html#ValueError) для недопустимых именованных аргументов.775776#### `somenamedtuple._fields`777778Кортеж строк с именами полей. Полезен для интроспекции и для создания новых типов именованных кортежей из существующих.779780```pycon781>>> p._fields            # просмотреть имена полей782('x', 'y')783784>>> Color = namedtuple('Color', 'red green blue')785>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)786>>> Pixel(11, 22, 128, 255, 0)787Pixel(x=11, y=22, red=128, green=255, blue=0)788```789790#### `somenamedtuple._field_defaults`791792Словарь, отображающий имена полей в значения по умолчанию.793794```pycon795>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])796>>> Account._field_defaults797{'balance': 0}798>>> Account('premium')799Account(type='premium', balance=0)800```801802Чтобы получить поле, имя которого хранится в строке, используйте функцию [`getattr()`](https://python-all.ru/3/library/functions.html#getattr) :803804```python805>>> getattr(p, 'x')80611807```808809Чтобы преобразовать словарь в именованный кортеж, используйте оператор двойной звёздочки (как описано в разделе [Распаковка списков аргументов](https://python-all.ru/3/tutorial/controlflow.html#tut-unpacking-arguments)):810811```python812>>> d = {'x': 11, 'y': 22}813>>> Point(**d)814Point(x=11, y=22)815```816817Поскольку именованный кортеж – это обычный класс Python, легко добавить или изменить функциональность с помощью подкласса. Вот как добавить вычисляемое поле и формат печати с фиксированной шириной:818819```pycon820>>> class Point(namedtuple('Point', ['x', 'y'])):821...     __slots__ = ()822...     @property823...     def hypot(self):824...         return (self.x ** 2 + self.y ** 2) ** 0.5825...     def __str__(self):826...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)827828>>> for p in Point(3, 4), Point(14, 5/7):829...     print(p)830Point: x= 3.000  y= 4.000  hypot= 5.000831Point: x=14.000  y= 0.714  hypot=14.018832```833834Подкласс, показанный выше, устанавливает `__slots__` в пустой кортеж. Это помогает снизить требования к памяти, предотвращая создание словарей экземпляров.835836Наследование не подходит для добавления новых хранимых полей. Вместо этого просто создайте новый тип именованного кортежа из атрибута [`_fields`](https://python-all.ru/3/library/collections.html#collections.somenamedtuple._fields):837838```python839>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))840```841842Докстринги можно настроить, напрямую присваивая значения полям `__doc__` :843844```python845>>> Book = namedtuple('Book', ['id', 'title', 'authors'])846>>> Book.__doc__ += ': Hardcover book in active collection'847>>> Book.id.__doc__ = '13-digit ISBN'848>>> Book.title.__doc__ = 'Title of first printing'849>>> Book.authors.__doc__ = 'List of authors sorted by last name'850```851852Изменено в версии 3.5: Докстринги свойств стали доступны для записи.853854> **См. также**855>856> - Смотрите [`typing.NamedTuple`](https://python-all.ru/3/library/typing.html#typing.NamedTuple) для способа добавления подсказок типов для именованных кортежей. Он также предоставляет элегантную запись с использованием ключевого слова [`class`](https://python-all.ru/3/reference/compound_stmts.html#class) :857>858>   ```python859>   class Component(NamedTuple):860>       part_number: int861>       weight: float862>       description: Optional[str] = None863>   ```864> - Смотрите [`types.SimpleNamespace()`](https://python-all.ru/3/library/types.html#types.SimpleNamespace) для изменяемого пространства имён на основе словаря вместо кортежа.865> - Модуль [`dataclasses`](https://python-all.ru/3/library/dataclasses.html#module-dataclasses) предоставляет декоратор и функции для автоматического добавления сгенерированных специальных методов в пользовательские классы.866867## [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) Объекты868869Упорядоченные словари похожи на обычные словари, но имеют некоторые дополнительные возможности, связанные с операциями упорядочивания. Они стали менее важны, поскольку встроенный класс [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) получил возможность запоминать порядок вставки (это новое поведение стало гарантированным в Python 3.7).870871Некоторые отличия от [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) всё ещё остаются:872873- Обычный [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) был спроектирован для очень хорошей работы с операциями отображения. Отслеживание порядка вставки было второстепенным.874- [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) был спроектирован для хорошей работы с операциями переупорядочивания. Эффективность использования памяти, скорость итерации и производительность операций обновления были второстепенными.875- Алгоритм [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) может обрабатывать частые операции переупорядочивания лучше, чем [`dict`](https://python-all.ru/3/library/stdtypes.html#dict). Как показано в рецептах ниже, это делает его подходящим для реализации различных типов LRU-кэшей.876- Операция равенства для [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) проверяет соответствие порядка.877878  Обычный [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) может эмулировать проверку равенства, чувствительную к порядку, с помощью `p == q and all(k1 == k2 for k1, k2 in zip(p, q))`.879- Метод [`popitem()`](https://python-all.ru/3/library/collections.html#collections.OrderedDict.popitem) у [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) имеет другую сигнатуру. Он принимает необязательный аргумент для указания того, какой элемент извлекается.880881  Обычный [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) может эмулировать OrderedDict.`od.popitem(last=True)` с помощью `d.popitem()`, который гарантированно извлекает крайний правый (последний) элемент.882883  Обычный [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) может эмулировать OrderedDict.`od.popitem(last=False)` с помощью `(k := next(iter(d)), d.pop(k))`, который вернёт и удалит крайний левый (первый) элемент, если он существует.884- У [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) есть метод [`move_to_end()`](https://python-all.ru/3/library/collections.html#collections.OrderedDict.move_to_end) для эффективного перемещения элемента в конечную позицию.885886  Обычный [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) может эмулировать OrderedDict.`od.move_to_end(k, last=True)` с помощью `d[k] = d.pop(k)`, который переместит ключ и связанное с ним значение в крайнюю правую (последнюю) позицию.887888  У обычного [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) нет эффективного эквивалента для OrderedDict.`od.move_to_end(k, last=False)`, который перемещает ключ и связанное с ним значение в крайнюю левую (первую) позицию.889- До Python 3.8 у [`dict`](https://python-all.ru/3/library/stdtypes.html#dict) отсутствовал метод [`__reversed__()`](https://python-all.ru/3/reference/datamodel.html#object.__reversed__).890891#### `class collections.OrderedDict(**kwargs)`892893#### `class collections.OrderedDict(mapping, /, **kwargs)`894895#### `class collections.OrderedDict(iterable, /, **kwargs)`896897Возвращает экземпляр подкласса [`dict`](https://python-all.ru/3/library/stdtypes.html#dict), который содержит методы для перестановки порядка словаря.898899Добавлено в версии 3.1.900901#### `popitem(last=True)`902903Метод `popitem()` для упорядоченных словарей возвращает и удаляет пару (key, value). Пары возвращаются в порядке LIFO, если *last* истинно, или в порядке FIFO, если ложно.904905#### `move_to_end(key, last=True)`906907Перемещает существующий *ключ* в начало или конец упорядоченного словаря. Элемент перемещается в конец, если *last* истинно (по умолчанию), или в начало, если *last* ложно. Вызывает [`KeyError`](https://python-all.ru/3/library/exceptions.html#KeyError), если *ключ* не существует:908909```pycon910>>> d = OrderedDict.fromkeys('abcde')911>>> d.move_to_end('b')912>>> ''.join(d)913'acdeb'914>>> d.move_to_end('b', last=False)915>>> ''.join(d)916'bacde'917```918919Добавлено в версии 3.2.920921Помимо обычных методов отображений, упорядоченные словари также поддерживают обратную итерацию с помощью [`reversed()`](https://python-all.ru/3/library/functions.html#reversed).922923Проверки на равенство между объектами [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) учитывают порядок и примерно эквивалентны `list(od1.items())==list(od2.items())`.924925Проверки на равенство между объектами [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) и другими объектами [`Mapping`](https://python-all.ru/3/library/collections.abc.html#collections.abc.Mapping) не зависят от порядка, как и в обычных словарях. Это позволяет подставлять объекты `OrderedDict` везде, где используется обычный словарь.926927Изменено в версии 3.5: Представления [представления](https://python-all.ru/3/glossary.html#term-dictionary-view) элементов, ключей и значений объекта [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) теперь поддерживают обратную итерацию с помощью [`reversed()`](https://python-all.ru/3/library/functions.html#reversed).928929Изменено в версии 3.6: С принятием [**PEP 468**](https://python-all.ru/3/library/collections.html) порядок сохраняется для именованных аргументов, передаваемых конструктору [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) и его методу [`update()`](https://python-all.ru/3/library/stdtypes.html#dict.update) .930931Изменено в версии 3.9: Добавлены операторы слияния (`|`) и обновления (`|=`), описанные в [**PEP 584**](https://python-all.ru/3/library/collections.html).932933### [`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) Примеры и рецепты934935It is straightforward to create an ordered dictionary variant that remembers the order the keys were *last* inserted. If a new entry overwrites an existing entry, the original insertion position is changed and moved to the end:936937```python938class LastUpdatedOrderedDict(OrderedDict):939    'Store items in the order the keys were last added'940941    def __setitem__(self, key, value):942        super().__setitem__(key, value)943        self.move_to_end(key)944```945946[`OrderedDict`](https://python-all.ru/3/library/collections.html#collections.OrderedDict) также был бы полезен для реализации вариантов [`functools.lru_cache()`](https://python-all.ru/3/library/functools.html#functools.lru_cache):947948```python949from collections import OrderedDict950from time import monotonic951952class TimeBoundedLRU:953    "LRU Cache that invalidates and refreshes old entries."954955    def __init__(self, func, maxsize=128, maxage=30):956        self.cache = OrderedDict()      # { args : (timestamp, result)}957        self.func = func958        self.maxsize = maxsize959        self.maxage = maxage960961    def __call__(self, *args):962        if args in self.cache:963            self.cache.move_to_end(args)964            timestamp, result = self.cache[args]965            if monotonic() - timestamp <= self.maxage:966                return result967        result = self.func(*args)968        self.cache[args] = monotonic(), result969        if len(self.cache) > self.maxsize:970            self.cache.popitem(last=False)971        return result972```973974```python975class MultiHitLRUCache:976    """ LRU-кэш, который откладывает кэширование результата, пока977        он не будет запрошен несколько раз.978979        Чтобы избежать сброса LRU-кэша однократными запросами,980        мы не кэшируем, пока запрос не будет сделан более одного раза.981982    """983984    def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1):985        self.requests = OrderedDict()   # { uncached_key : request_count }986        self.cache = OrderedDict()      # { cached_key : function_result }987        self.func = func988        self.maxrequests = maxrequests  # максимальное количество некэшированных запросов989        self.maxsize = maxsize          # максимальное количество сохранённых возвращаемых значений990        self.cache_after = cache_after991992    def __call__(self, *args):993        if args in self.cache:994            self.cache.move_to_end(args)995            return self.cache[args]996        result = self.func(*args)997        self.requests[args] = self.requests.get(args, 0) + 1998        if self.requests[args] <= self.cache_after:999            self.requests.move_to_end(args)1000            if len(self.requests) > self.maxrequests:1001                self.requests.popitem(last=False)1002        else:1003            self.requests.pop(args, None)1004            self.cache[args] = result1005            if len(self.cache) > self.maxsize:1006                self.cache.popitem(last=False)1007        return result1008```10091010## [`UserDict`](https://python-all.ru/3/library/collections.html#collections.UserDict)Объекты10111012Класс [`UserDict`](https://python-all.ru/3/library/collections.html#collections.UserDict) действует как обёртка вокруг объектов-словарей. Необходимость в этом классе отчасти утрачена из-за возможности наследовать напрямую от [`dict`](https://python-all.ru/3/library/stdtypes.html#dict); однако с ним может быть проще работать, поскольку базовый словарь доступен как атрибут.10131014#### `class collections.UserDict(**kwargs)`10151016#### `class collections.UserDict(mapping, /, **kwargs)`10171018#### `class collections.UserDict(iterable, /, **kwargs)`10191020Класс, который имитирует словарь. Содержимое экземпляра хранится в обычном словаре, доступном через атрибут [`data`](https://python-all.ru/3/library/collections.html#collections.UserDict.data) экземпляров `UserDict`. Если переданы аргументы, они используются для инициализации `data`, как в обычном словаре.10211022В дополнение к поддержке методов и операций отображений, экземпляры `UserDict` предоставляют следующий атрибут:10231024#### `data`10251026Реальный словарь, используемый для хранения содержимого класса `UserDict` .10271028## [`UserList`](https://python-all.ru/3/library/collections.html#collections.UserList)Объекты10291030Этот класс действует как обёртка вокруг объектов-списков. Это полезный базовый класс для собственных классов, подобных спискам, которые могут наследовать от них и переопределять существующие методы или добавлять новые. Таким образом, можно добавлять новое поведение к спискам.10311032Необходимость в этом классе отчасти утрачена из-за возможности наследовать напрямую от [`list`](https://python-all.ru/3/library/stdtypes.html#list); однако с этим классом может быть проще работать, поскольку базовый список доступен как атрибут.10331034#### `class collections.UserList([list])`10351036Класс, который имитирует список. Содержимое экземпляра хранится в обычном списке, доступном через атрибут [`data`](https://python-all.ru/3/library/collections.html#collections.UserList.data) экземпляров `UserList`. Содержимое экземпляра изначально устанавливается как копия *list*, по умолчанию – пустой список `[]`. *list* может быть любым итерируемым объектом, например настоящим списком Python или объектом `UserList`.10371038В дополнение к поддержке методов и операций изменяемых последовательностей, экземпляры `UserList` предоставляют следующий атрибут:10391040#### `data`10411042Реальный объект [`list`](https://python-all.ru/3/library/stdtypes.html#list), используемый для хранения содержимого класса `UserList`.10431044**Требования к подклассам:** Ожидается, что подклассы [`UserList`](https://python-all.ru/3/library/collections.html#collections.UserList) предоставляют конструктор, который можно вызывать без аргументов или с одним аргументом. Операции со списками, возвращающие новую последовательность, пытаются создать экземпляр фактического класса реализации. Для этого предполагается, что конструктор можно вызвать с одним параметром – объектом-последовательностью, используемым как источник данных.10451046Если производный класс не желает соблюдать это требование, все специальные методы, поддерживаемые этим классом, должны быть переопределены; обратитесь к исходному коду за информацией о методах, которые необходимо предоставить в этом случае.10471048## [`UserString`](https://python-all.ru/3/library/collections.html#collections.UserString) объекты10491050Класс [`UserString`](https://python-all.ru/3/library/collections.html#collections.UserString) выступает в качестве обёртки для строковых объектов. Необходимость в этом классе частично отпала благодаря возможности создания подклассов непосредственно от [`str`](https://python-all.ru/3/library/stdtypes.html#str); однако с этим классом может быть проще работать, так как базовая строка доступна в виде атрибута.10511052#### `class collections.UserString(seq)`10531054Класс, который имитирует строковый объект. Содержимое экземпляра хранится в обычном строковом объекте, доступ к которому осуществляется через атрибут [`data`](https://python-all.ru/3/library/collections.html#collections.UserString.data) экземпляров `UserString`. Содержимое экземпляра изначально устанавливается в копию *seq*. Аргумент *seq* может быть любым объектом, который можно преобразовать в строку с помощью встроенной функции [`str()`](https://python-all.ru/3/library/stdtypes.html#str).10551056В дополнение к поддержке методов и операций со строками, экземпляры `UserString` предоставляют следующий атрибут:10571058#### `data`10591060Настоящий объект [`str`](https://python-all.ru/3/library/stdtypes.html#str), используемый для хранения содержимого класса `UserString`.10611062Изменено в версии 3.5: Новые методы `__getnewargs__`, `__rmod__`, `casefold`, `format_map`, `isprintable` и `maketrans`.1063