# `collections` — Container datatypes

Вихідний код: Lib/collections/__init__.py

Цей модуль реалізує спеціалізовані типи даних контейнерів, що є альтернативою вбудованим контейнерам загального призначення Python, `dict`, `list`, `set` і `tuple`.

`namedtuple()` | функція фабрики для створення підкласів кортежів з іменованими полями
`deque` | контейнер, схожий на список, із швидким додаванням і вискакуванням на обох кінцях
`ChainMap` | dict-подібний клас для створення єдиного перегляду кількох відображень
`Counter` | dict subclass for counting hashable objects
`OrderedDict` | підклас dict, який запам’ятовує додані записи порядку
`defaultdict` | підклас dict, який викликає фабричну функцію для надання відсутніх значень
`UserDict` | обгортка навколо об’єктів словника для легшого створення підкласів dict
`UserList` | обгортка навколо об’єктів списку для легшого створення підкласів списку
`UserString` | обгортка навколо рядкових об’єктів для легшого створення підкласів рядків

## `ChainMap` об’єкти

Added in version 3.3.

Клас `ChainMap` надається для швидкого зв’язування кількох відображень, щоб їх можна було розглядати як єдине ціле. Часто це набагато швидше, ніж створення нового словника та виконання кількох викликів `update()`.

Клас можна використовувати для імітації вкладених областей і корисний у створенні шаблонів.

class collections.ChainMap(*maps)

  `ChainMap` групує кілька dicts або інших відображень разом, щоб створити єдине оновлюване подання. Якщо maps не вказано, надається єдиний порожній словник, щоб новий ланцюжок завжди мав принаймні одне відображення.

  Базові відображення зберігаються в списку. Цей список є загальнодоступним, і до нього можна отримати доступ або оновити за допомогою атрибута maps. Іншої держави немає.

  Пошуки послідовно шукають базові відображення, доки не буде знайдено ключ. Навпаки, записи, оновлення та видалення діють лише на першому відображенні.

  `ChainMap` включає базові відображення за посиланням. Отже, якщо одне з базових відображень буде оновлено, ці зміни буде відображено в `ChainMap`.

  Підтримуються всі звичайні словникові методи. Крім того, існує атрибут maps, метод для створення нових підконтекстів і властивість для доступу до всіх відображень, крім першого:

  maps

    Список відображень, який можна оновлювати користувачем. Список упорядковано від першого до останнього. Це єдиний стан, який зберігається, і його можна змінити, щоб змінити зіставлення, які шукаються. Список завжди повинен містити принаймні одне зіставлення.

  new_child(m=None, **kwargs)

    Повертає новий `ChainMap`, який містить нову карту, за якою слідують усі карти в поточному екземплярі. Якщо вказано `m`, воно стає новою картою на початку списку зіставлень; якщо не вказано, використовується порожній dict, так що виклик `d.new_child()` еквівалентний: `ChainMap({}, *d.maps)`. Якщо вказано будь-які аргументи ключового слова, вони оновлюють передану карту або новий порожній dict. Цей метод використовується для створення підконтекстів, які можна оновлювати без зміни значень у будь-якому з батьківських відображень.

    Змінено в версії 3.4: Додано необов’язковий параметр `m`.

    Змінено в версії 3.10: Додано підтримку аргументів ключових слів.

  parents

    Властивість, що повертає новий `ChainMap`, що містить усі карти в поточному екземплярі, крім першої. Це корисно для пропуску першої карти в пошуку. Випадки використання схожі на випадки використання ключового слова `nonlocal`, що використовується у вкладених областях. Випадки використання також аналогічні використанню вбудованої функції `super()`. Посилання на `d.parents` еквівалентне: `ChainMap(*d.maps[1:])`.

  Note, the iteration order of a `ChainMap` is determined by scanning the mappings last to first:

      >>> baseline = {'music': 'bach', 'art': 'rembrandt'}
      >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'}
      >>> list(ChainMap(adjustments, baseline))
      ['music', 'art', 'opera']

  Це дає такий самий порядок, як і серія викликів `dict.update()`, починаючи з останнього відображення:

      >>> combined = baseline.copy()
      >>> combined.update(adjustments)
      >>> list(combined)
      ['music', 'art', 'opera']

  Змінено в версії 3.9: Додано підтримку операторів `|` і `|=`, указаних у PEP 584.

Дивись також

- MultiContext class у пакеті Enthought CodeTools має опції для підтримки запису в будь-яке відображення в ланцюжку.

- Клас контексту Django для створення шаблонів — це ланцюжок відображень лише для читання. Він також має функцію надсилання та витягування контекстів, подібних до методу `new_child()` і властивості `parents`.

- The Nested Contexts recipe has options to control whether writes and other mutations apply only to the first mapping or to any mapping in the chain.

- Значно спрощена версія Chainmap тільки для читання.

### `ChainMap` Приклади та рецепти

У цьому розділі показано різні підходи до роботи з ланцюжковими картами.

Приклад симуляції внутрішнього ланцюжка пошуку Python:

    import builtins
    pylookup = ChainMap(locals(), globals(), vars(builtins))

Приклад надання переваги заданим користувачем аргументам командного рядка над змінними середовища, які, у свою чергу, мають пріоритет над значеннями за замовчуванням:

    import os, argparse

    defaults = {'color': 'red', 'user': 'guest'}

    parser = argparse.ArgumentParser()
    parser.add_argument('-u', '--user')
    parser.add_argument('-c', '--color')
    namespace = parser.parse_args()
    command_line_args = {k: v for k, v in vars(namespace).items() if v is not None}

    combined = ChainMap(command_line_args, os.environ, defaults)
    print(combined['color'])
    print(combined['user'])

Приклади шаблонів використання класу `ChainMap` для імітації вкладених контекстів:

    c = ChainMap()        # Create root context
    d = c.new_child()     # Create nested child context
    e = c.new_child()     # Child of c, independent from d
    e.maps[0]             # Current context dictionary -- like Python's locals()
    e.maps[-1]            # Root context -- like Python's globals()
    e.parents             # Enclosing context chain -- like Python's nonlocals

    d['x'] = 1            # Set value in current context
    d['x']                # Get first key in the chain of contexts
    del d['x']            # Delete from current context
    list(d)               # All nested values
    k in d                # Check all nested values
    len(d)                # Number of nested values
    d.items()             # All nested items
    dict(d)               # Flatten into a regular dictionary

Клас `ChainMap` лише оновлює (записує та видаляє) перше відображення в ланцюжку, тоді як пошук шукатиме повний ланцюжок. Однак, якщо потрібні глибокі записи та видалення, легко створити підклас, який оновлює ключі, знайдені глибше в ланцюжку:

    class DeepChainMap(ChainMap):
        'Variant of ChainMap that allows direct updates to inner scopes'

        def __setitem__(self, key, value):
            for mapping in self.maps:
                if key in mapping:
                    mapping[key] = value
                    return
            self.maps[0][key] = value

        def __delitem__(self, key):
            for mapping in self.maps:
                if key in mapping:
                    del mapping[key]
                    return
            raise KeyError(key)

    >>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
    >>> d['lion'] = 'orange'         # update an existing key two levels down
    >>> d['snake'] = 'red'           # new keys get added to the topmost dict
    >>> del d['elephant']            # remove an existing key one level down
    >>> d                            # display result
    DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})

## `Counter` об’єкти

Надається інструмент лічильника для зручного та швидкого підрахунку. Наприклад:

    >>> # Tally occurrences of words in a list
    >>> cnt = Counter()
    >>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
    ...     cnt[word] += 1
    ...
    >>> cnt
    Counter({'blue': 3, 'red': 2, 'green': 1})

    >>> # Find the ten most common words in Hamlet
    >>> import re
    >>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
    >>> Counter(words).most_common(10)
    [('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
     ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]

class collections.Counter([iterable-or-mapping])

  A `Counter` is a `dict` subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The `Counter` class is similar to bags or multisets in other languages.

  Елементи підраховуються з iterable або ініціалізуються з іншого mapping (або лічильника):

      >>> c = Counter()                           # a new, empty counter
      >>> c = Counter('gallahad')                 # a new counter from an iterable
      >>> c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
      >>> c = Counter(cats=4, dogs=8)             # a new counter from keyword args

  Об’єкти лічильників мають інтерфейс словника, за винятком того, що вони повертають нульову кількість для відсутніх елементів замість того, щоб викликати `KeyError`:

      >>> c = Counter(['eggs', 'ham'])
      >>> c['bacon']                              # count of a missing element is zero
      0

  Встановлення лічильника на нуль не видаляє елемент із лічильника. Використовуйте `del`, щоб видалити його повністю:

      >>> c['sausage'] = 0                        # counter entry with a zero count
      >>> del c['sausage']                        # del actually removes the entry

  Added in version 3.1.

  Змінено в версії 3.7: Як підклас `dict`, `Counter` успадкував можливість запам’ятовувати порядок вставки. Математичні операції над об’єктами Counter також зберігають порядок. Результати впорядковуються відповідно до того, коли елемент вперше зустрічається в лівому операнді, а потім у порядку зустрічі в правому операнді.

  Об’єкти лічильників підтримують додаткові методи, окрім тих, що доступні для всіх словників:

  elements()

    Повертає ітератор над елементами, повторюючи кожен стільки разів, скільки його кількість. Елементи повертаються в тому порядку, в якому вони зустрічаються першими. Якщо кількість елемента менше одиниці, `elements()` проігнорує його.

        >>> c = Counter(a=4, b=2, c=0, d=-2)
        >>> sorted(c.elements())
        ['a', 'a', 'a', 'a', 'b', 'b']

  most_common([n])

    Повертає список з n найпоширеніших елементів і їх підрахунок від найбільш поширених до найменших. Якщо n пропущено або `None`, `most_common()` повертає всі елементи в лічильнику. Елементи з рівною кількістю впорядковуються в порядку, коли вони зустрічаються першими:

        >>> Counter('abracadabra').most_common(3)
        [('a', 5), ('b', 2), ('r', 2)]

  subtract([iterable-or-mapping])

    Елементи віднімаються з iterable або з іншого mapping (або лічильника). Подібно до `dict.update()`, але кількість віднімає, а не замінює. І входи, і виходи можуть бути нульовими або негативними.

        >>> c = Counter(a=4, b=2, c=0, d=-2)
        >>> d = Counter(a=1, b=2, c=3, d=4)
        >>> c.subtract(d)
        >>> c
        Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

    Added in version 3.2.

  total()

    Обчисліть суму підрахунків.

        >>> c = Counter(a=10, b=5, c=0)
        >>> c.total()
        15

    Added in version 3.10.

  Звичайні методи словника доступні для об’єктів `Counter`, за винятком двох, які працюють по-різному для лічильників.

  fromkeys(iterable)

    Цей метод класу не реалізований для об’єктів `Counter`.

  update([iterable-or-mapping])

    Елементи підраховуються від iterable або add-in від іншого mapping (або лічильника). Як `dict.update()`, але додає лічильники замість їх заміни. Крім того, очікується, що iterable буде послідовністю елементів, а не послідовністю пар `(ключ, значення)`.

Лічильники підтримують розширені оператори порівняння для зв’язків рівності, підмножини та надмножини: `==`, `!=`, `<`, `<=`, `>`, `>=`. Усі ці тести розглядають відсутні елементи як такі, що мають нульову кількість, тому `Counter(a=1) == Counter(a=1, b=0)` повертає true.

Змінено в версії 3.10: Додано розширені операції порівняння.

Змінено в версії 3.10: У тестах на рівність відсутні елементи розглядаються як такі, що мають нульову кількість. Раніше `Counter(a=3)` і `Counter(a=3, b=0)` вважалися різними.

Загальні шаблони для роботи з об’єктами `Counter`:

    c.total()                       # total of all counts
    c.clear()                       # reset all counts
    list(c)                         # list unique elements
    set(c)                          # convert to a set
    dict(c)                         # convert to a regular dictionary
    c.items()                       # access the (elem, cnt) pairs
    Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
    c.most_common()[:-n-1:-1]       # n least common elements
    +c                              # remove zero and negative counts

Передбачено кілька математичних операцій для об’єднання об’єктів `Counter` для створення мультимножин (лічильників, які мають кількість, більшу за нуль). Додавання та віднімання поєднують лічильники шляхом додавання або віднімання підрахунків відповідних елементів. Перетин і об’єднання повертають мінімальне та максимальне значення відповідних підрахунків. Рівність і включення порівнюють відповідні підрахунки. Кожна операція може приймати вхідні дані зі знаком підрахунків, але вихід виключатиме результати з нульовими чи меншими значеннями.

    >>> c = Counter(a=3, b=1)
    >>> d = Counter(a=1, b=2)
    >>> c + d                       # add two counters together:  c[x] + d[x]
    Counter({'a': 4, 'b': 3})
    >>> c - d                       # subtract (keeping only positive counts)
    Counter({'a': 2})
    >>> c & d                       # intersection:  min(c[x], d[x])
    Counter({'a': 1, 'b': 1})
    >>> c | d                       # union:  max(c[x], d[x])
    Counter({'a': 3, 'b': 2})
    >>> c == d                      # equality:  c[x] == d[x]
    False
    >>> c <= d                      # inclusion:  c[x] <= d[x]
    False

Унарне додавання та віднімання — це ярлики для додавання порожнього лічильника або віднімання з порожнього лічильника.

    >>> c = Counter(a=2, b=-4)
    >>> +c
    Counter({'a': 2})
    >>> -c
    Counter({'b': 4})

Added in version 3.3: Додано підтримку унарних операцій плюс, унарний мінус і мультимножинних операцій на місці.

Примітка

Лічильники були в основному розроблені для роботи з позитивними цілими числами для представлення поточних підрахунків; однак було вжито заходів для того, щоб без потреби не виключити випадки використання, які потребують інших типів або від’ємних значень. Щоб допомогти з цими випадками використання, у цьому розділі описані мінімальні обмеження діапазону та типу.

- Сам клас `Counter` є підкласом словника без обмежень щодо його ключів і значень. Значення мають бути числами, що представляють кількість, але ви можете зберігати будь-що в полі значення.

- Метод `most_common()` вимагає лише того, щоб значення можна було впорядкувати.

- Для операцій на місці, таких як `c[key] += 1`, тип значення потребує лише підтримки додавання та віднімання. Отже, дроби, числа з плаваючою точкою та десяткові дроби працюватимуть, а від’ємні значення підтримуються. Те ж саме вірно для `update()` і `subtract()`, які дозволяють від’ємні та нульові значення як для входів, так і для виходів.

- Мультимножинні методи призначені лише для випадків використання з позитивними значеннями. Вхідні дані можуть бути від’ємними або нульовими, але створюються лише виходи з позитивними значеннями. Немає обмежень щодо типів, але тип значення має підтримувати додавання, віднімання та порівняння.

- Метод `elements()` вимагає підрахунку цілих чисел. Він ігнорує нульові та негативні значення.

Дивись також

- Клас сумки у Smalltalk.

- Запис у Вікіпедії для Мультимножини.

- C++ multisets посібник із прикладами.

- Про математичні операції над мультимножинами та випадки їх використання див. Knuth, Donald. Мистецтво комп’ютерного програмування, том II, розділ 4.6.3, вправа 19.

- Щоб перерахувати всі різні мультимножини заданого розміру над заданим набором елементів, перегляньте `itertools.combinations_with_replacement()`:

      map(Counter, combinations_with_replacement('ABC', 2)) # --> AA AB AC BB BC CC

## `deque` об’єкти

class collections.deque([iterable[, maxlen]])

  Повертає новий об’єкт deque, ініціалізований зліва направо (за допомогою `append()`) з даними з iterable. Якщо iterable не вказано, нова двочерга порожня.

  Deques are a generalization of stacks and queues (the name is pronounced «deck» and is short for «double-ended queue»). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.

  Though `list` objects support similar operations, they are optimized for fast fixed-length operations and incur O(n) memory movement costs for `pop(0)` and `insert(0, v)` operations which change both the size and position of the underlying data representation.

  Якщо maxlen не вказано або має значення `None`, дві версії можуть зростати до довільної довжини. В іншому випадку двочерга обмежена до вказаної максимальної довжини. Коли двочерга обмеженої довжини заповнюється, коли додаються нові елементи, відповідна кількість елементів відкидається з протилежного кінця. Обмежена довжина двох рядків забезпечує функціональність, подібну до фільтра `tail` в Unix. Вони також корисні для відстеження транзакцій та інших наборів даних, де цікаві лише останні дії.

  Об’єкти Deque підтримують такі методи:

  append(x)

    Додайте x до правої сторони дека.

  appendleft(x)

    Додайте x до лівої сторони дека.

  clear()

    Видаліть усі елементи з двоканального ряду, залишивши його довжиною 0.

  copy()

    Створіть поверхневу копію deque.

    Added in version 3.5.

  count(x)

    Підрахуйте кількість елементів deque, що дорівнює x.

    Added in version 3.2.

  extend(iterable)

    Розширте праву частину двоканального ряду, додавши елементи з ітерованого аргументу.

  extendleft(iterable)

    Розширте ліву сторону двостороннього коду, додавши елементи з iterable. Зауважте, що серія лівих додань призводить до зміни порядку елементів у повторюваному аргументі.

  index(x[, start[, stop]])

    Повертає позицію x у черзі (за індексом start і перед індексом stop). Повертає перший збіг або викликає `ValueError`, якщо не знайдено.

    Added in version 3.5.

  insert(i, x)

    Вставте x у рядок у позицію i.

    Якщо вставка призведе до того, що обмежена двочерга виросте за межі maxlen, виникає `IndexError`.

    Added in version 3.5.

  pop()

    Видаліть і поверніть елемент з правого боку двоканальної таблиці. Якщо немає елементів, викликає `IndexError`.

  popleft()

    Видаліть і поверніть елемент з лівої сторони двосторонньої версії. Якщо немає елементів, викликає `IndexError`.

  remove(value)

    Видаліть перше входження значення. Якщо не знайдено, викликає `ValueError`.

  reverse()

    Перевернути елементи дек-версії на місці, а потім повернути `None`.

    Added in version 3.2.

  rotate(n=1)

    Поверніть двічі n кроків праворуч. Якщо n від’ємне, поверніть ліворуч.

    Якщо двочерга не порожня, поворот на один крок праворуч еквівалентний d.appendleft(d.pop()) , а поворот на один крок ліворуч еквівалентний d.append(d.popleft ())``.

  Об’єкти Deque також надають один атрибут лише для читання:

  maxlen

    Максимальний розмір двочергового рядка або `None`, якщо необмежений.

    Added in version 3.1.

In addition to the above, deques support iteration, pickling, `len(d)`, `reversed(d)`, `copy.copy(d)`, `copy.deepcopy(d)`, membership testing with the `in` operator, and subscript references such as `d[0]` to access the first element. Indexed access is O(1) at both ends but slows to O(n) in the middle. For fast random access, use lists instead.

Починаючи з версії 3.5, deques підтримують `__add__()`, `__mul__()` і `__imul__()`.

приклад:

    >>> from collections import deque
    >>> d = deque('ghi')                 # make a new deque with three items
    >>> for elem in d:                   # iterate over the deque's elements
    ...     print(elem.upper())
    G
    H
    I

    >>> d.append('j')                    # add a new entry to the right side
    >>> d.appendleft('f')                # add a new entry to the left side
    >>> d                                # show the representation of the deque
    deque(['f', 'g', 'h', 'i', 'j'])

    >>> d.pop()                          # return and remove the rightmost item
    'j'
    >>> d.popleft()                      # return and remove the leftmost item
    'f'
    >>> list(d)                          # list the contents of the deque
    ['g', 'h', 'i']
    >>> d[0]                             # peek at leftmost item
    'g'
    >>> d[-1]                            # peek at rightmost item
    'i'

    >>> list(reversed(d))                # list the contents of a deque in reverse
    ['i', 'h', 'g']
    >>> 'h' in d                         # search the deque
    True
    >>> d.extend('jkl')                  # add multiple elements at once
    >>> d
    deque(['g', 'h', 'i', 'j', 'k', 'l'])
    >>> d.rotate(1)                      # right rotation
    >>> d
    deque(['l', 'g', 'h', 'i', 'j', 'k'])
    >>> d.rotate(-1)                     # left rotation
    >>> d
    deque(['g', 'h', 'i', 'j', 'k', 'l'])

    >>> deque(reversed(d))               # make a new deque in reverse order
    deque(['l', 'k', 'j', 'i', 'h', 'g'])
    >>> d.clear()                        # empty the deque
    >>> d.pop()                          # cannot pop from an empty deque
    Traceback (most recent call last):
        File "<pyshell#6>", line 1, in -toplevel-
            d.pop()
    IndexError: pop from an empty deque

    >>> d.extendleft('abc')              # extendleft() reverses the input order
    >>> d
    deque(['c', 'b', 'a'])

### `deque` Рецепти

У цьому розділі показано різні підходи до роботи з deque.

Обмежена довжина двостороннього ряду забезпечує функціональність, подібну до фільтра `tail` в Unix:

    def tail(filename, n=10):
        'Return the last n lines of a file'
        with open(filename) as f:
            return deque(f, n)

Інший підхід до використання двох блоків полягає в підтримці послідовності нещодавно доданих елементів шляхом додавання праворуч і висування ліворуч:

    def moving_average(iterable, n=3):
        # moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
        # https://en.wikipedia.org/wiki/Moving_average
        it = iter(iterable)
        d = deque(itertools.islice(it, n-1))
        d.appendleft(0)
        s = sum(d)
        for elem in it:
            s += elem - d.popleft()
            d.append(elem)
            yield s / n

Циклічний планувальник може бути реалізований за допомогою ітераторів введення, що зберігаються в `deque`. Значення виводяться з активного ітератора в нульовій позиції. Якщо цей ітератор вичерпано, його можна видалити за допомогою `popleft()`; інакше його можна повернути до кінця за допомогою методу `rotate()`:

    def roundrobin(*iterables):
        "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
        iterators = deque(map(iter, iterables))
        while iterators:
            try:
                while True:
                    yield next(iterators[0])
                    iterators.rotate(-1)
            except StopIteration:
                # Remove an exhausted iterator.
                iterators.popleft()

Метод `rotate()` забезпечує спосіб реалізації `deque` нарізки та видалення. Наприклад, чиста реалізація `del d[n]` на Python покладається на метод `rotate()` для позиціонування елементів, які потрібно відкрити:

    def delete_nth(d, n):
        d.rotate(-n)
        d.popleft()
        d.rotate(n)

Щоб реалізувати нарізку `deque`, скористайтеся подібним підходом, застосовуючи `rotate()`, щоб перемістити цільовий елемент у ліву сторону від deque. Видаліть старі записи за допомогою `popleft()`, додайте нові за допомогою `extend()`, а потім змініть чергування. З незначними варіаціями цього підходу легко реалізувати маніпуляції стеком у стилі Forth, такі як `dup`, `drop`, `swap`, `over`, `pick`, `rot` і `roll`.

## `defaultdict` об’єкти

class collections.defaultdict(default_factory=None, /[, ...])

  Повернути новий об’єкт, схожий на словник. `defaultdict` є підкласом вбудованого класу `dict`. Він замінює один метод і додає одну змінну екземпляра, доступну для запису. Інші функції такі ж, як і для класу `dict`, і тут не описані.

  Перший аргумент надає початкове значення для атрибута `default_factory`; за замовчуванням `None`. Усі решта аргументів обробляються так само, як якщо б вони були передані конструктору `dict`, включаючи аргументи ключових слів.

  Об’єкти `defaultdict` підтримують наступний метод на додаток до стандартних операцій `dict`:

  __missing__(key)

    Якщо атрибут `default_factory` має значення `None`, це викликає виключення `KeyError` з key як аргументом.

    Якщо `default_factory` не є `None`, він викликається без аргументів, щоб надати значення за замовчуванням для даного ключа, це значення вставляється в словник для ключа та повертається.

    Якщо виклик `default_factory` викликає виняток, цей виняток поширюється без змін.

    This method is called by the `__getitem__()` method of the `dict` class when the requested key is not found; whatever it returns or raises is then returned or raised by `__getitem__()`.

    Note that `__missing__()` is not called for any operations besides `__getitem__()`. This means that `get()` will, like normal dictionaries, return `None` as a default rather than using `default_factory`.

  Об’єкти `defaultdict` підтримують таку змінну екземпляра:

  default_factory

    Цей атрибут використовується методом `__missing__()`; він ініціалізується від першого аргументу до конструктора, якщо він присутній, або до `None`, якщо його немає.

  Змінено в версії 3.9: Додано оператори злиття (`|`) і оновлення (`|=`), указані в PEP 584.

### `defaultdict` Приклади

Використовуючи `list` як `default_factory`, можна легко згрупувати послідовність пар ключ-значення в словник списків:

    >>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
    >>> d = defaultdict(list)
    >>> for k, v in s:
    ...     d[k].append(v)
    ...
    >>> sorted(d.items())
    [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

Коли кожен ключ зустрічається вперше, його ще немає у відображенні; тому запис створюється автоматично за допомогою функції `default_factory`, яка повертає порожній `list`. Потім операція `list.append()` додає значення до нового списку. Коли ключі зустрічаються знову, пошук триває нормально (повертається список для цього ключа), а операція `list.append()` додає інше значення до списку. Ця техніка простіша та швидша, ніж еквівалентна техніка з використанням `dict.setdefault()`:

    >>> d = {}
    >>> for k, v in s:
    ...     d.setdefault(k, []).append(v)
    ...
    >>> sorted(d.items())
    [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

Встановлення `default_factory` на `int` робить `defaultdict` корисним для підрахунку (як сумка або мультинабір в інших мовах):

    >>> s = 'mississippi'
    >>> d = defaultdict(int)
    >>> for k in s:
    ...     d[k] += 1
    ...
    >>> sorted(d.items())
    [('i', 4), ('m', 1), ('p', 2), ('s', 4)]

Коли буква зустрічається вперше, вона відсутня у відображенні, тому функція `default_factory` викликає `int()`, щоб надати нульову кількість за умовчанням. Потім операція збільшення створює кількість для кожної літери.

Функція `int()`, яка завжди повертає нуль, є лише окремим випадком постійних функцій. Швидший і більш гнучкий спосіб створення постійних функцій полягає у використанні лямбда-функції, яка може надати будь-яке постійне значення (не лише нуль):

    >>> def constant_factory(value):
    ...     return lambda: value
    ...
    >>> d = defaultdict(constant_factory('<missing>'))
    >>> d.update(name='John', action='ran')
    >>> '%(name)s %(action)s to %(object)s' % d
    'John ran to <missing>'

Встановлення `default_factory` на `set` робить `defaultdict` корисним для створення словника наборів:

    >>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
    >>> d = defaultdict(set)
    >>> for k, v in s:
    ...     d[k].add(v)
    ...
    >>> sorted(d.items())
    [('blue', {2, 4}), ('red', {1, 3})]

## `namedtuple()` Фабрична функція для кортежів з іменованими полями

Іменовані кортежі призначають значення кожній позиції в кортежі та забезпечують більш читабельний самодокументований код. Їх можна використовувати скрізь, де використовуються звичайні кортежі, і вони додають можливість доступу до полів за назвою замість індексу позиції.

collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)

  Повертає новий підклас кортежу з назвою typename. Новий підклас використовується для створення кортежних об’єктів, які мають поля, доступні за допомогою пошуку атрибутів, а також які можна індексувати та повторювати. Екземпляри підкласу також мають корисний рядок документації (з назвою типу та іменами полів) і корисний метод `__repr__()`, який перераховує вміст кортежу у форматі `ім'я=значення`.

  Імена_полів — це послідовність рядків, наприклад `['x', 'y']`. Крім того, назви_полів можуть бути одним рядком із назвою кожного поля, розділеного пробілами та/або комами, наприклад `'x y'` або `'x, y'`.

  Для імені поля можна використовувати будь-який дійсний ідентифікатор Python, за винятком імен, що починаються з підкреслення. Дійсні ідентифікатори складаються з літер, цифр і підкреслення, але не починаються з цифри або підкреслення і не можуть бути `keyword`, таким як клас, для, повернення, глобальний, перехід , або підняти.

  Якщо rename має значення true, недійсні назви полів автоматично замінюються позиційними іменами. Наприклад, `['abc', 'def', 'ghi', 'abc']` перетворюється на `['abc', '_1', 'ghi', '_3']`, усуваючи ключове слово `def` і повторюване ім’я поля `abc`.

  defaults може бути `None` або iterable значень за замовчуванням. Оскільки поля зі значенням за замовчуванням мають бути після будь-яких полів без значення за замовчуванням, за замовчуванням застосовуються до крайніх правих параметрів. Наприклад, якщо імена полів `['x', 'y', 'z']`, а значення за умовчанням `(1, 2)`, тоді `x` буде обов’язковим аргументом, `y` за замовчуванням буде `1`, а `z` буде `2`.

  If module is defined, the `__module__` attribute of the named tuple is set to that value.

  Іменовані екземпляри кортежу не мають словників для кожного екземпляра, тому вони легкі та не вимагають більше пам’яті, ніж звичайні кортежі.

  Щоб підтримувати маринування, іменований клас кортежу має бути призначений змінній, яка відповідає typename.

  Змінено в версії 3.1: Додано підтримку перейменування.

  Змінено в версії 3.6: Параметри verbose і rename стали аргументами лише для ключових слів.

  Змінено в версії 3.6: Додано параметр module.

  Змінено в версії 3.7: Видалено параметр verbose і атрибут `_source`.

  Змінено в версії 3.7: Додано параметр defaults і атрибут `_field_defaults`.

    >>> # Basic example
    >>> Point = namedtuple('Point', ['x', 'y'])
    >>> p = Point(11, y=22)     # instantiate with positional or keyword arguments
    >>> p[0] + p[1]             # indexable like the plain tuple (11, 22)
    33
    >>> x, y = p                # unpack like a regular tuple
    >>> x, y
    (11, 22)
    >>> p.x + p.y               # fields also accessible by name
    33
    >>> p                       # readable __repr__ with a name=value style
    Point(x=11, y=22)

Іменовані кортежі особливо корисні для призначення імен полів кортежам результатів, які повертаються модулями `csv` або `sqlite3`:

    EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

    import csv
    for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
        print(emp.name, emp.title)

    import sqlite3
    conn = sqlite3.connect('/companydata')
    cursor = conn.cursor()
    cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
    for emp in map(EmployeeRecord._make, cursor.fetchall()):
        print(emp.name, emp.title)

На додаток до методів, успадкованих від кортежів, іменовані кортежі підтримують три додаткові методи та два атрибути. Щоб запобігти конфліктам імен полів, імена методів і атрибутів починаються зі знака підкреслення.

classmethod somenamedtuple._make(iterable)

  Метод класу, який створює новий екземпляр із існуючої послідовності або повторюється.

      >>> t = [11, 22]
      >>> Point._make(t)
      Point(x=11, y=22)

somenamedtuple._asdict()

  Повертає новий `dict`, який зіставляє назви полів з відповідними значеннями:

      >>> p = Point(x=11, y=22)
      >>> p._asdict()
      {'x': 11, 'y': 22}

  Змінено в версії 3.1: Повертає `OrderedDict` замість звичайного `dict`.

  Змінено в версії 3.8: Повертає звичайний `dict` замість `OrderedDict`. Починаючи з Python 3.7, звичайні dicts гарантовано будуть упорядковані. Якщо потрібні додаткові функції `OrderedDict`, запропонованим виправленням є приведення результату до потрібного типу: `OrderedDict(nt._asdict())`.

somenamedtuple._replace(**kwargs)

  Повертає новий екземпляр іменованого кортежу, замінюючи вказані поля новими значеннями:

      >>> p = Point(x=11, y=22)
      >>> p._replace(x=33)
      Point(x=33, y=22)

      >>> for partnum, record in inventory.items():
      ...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())

  Named tuples are also supported by generic function `copy.replace()`.

  Змінено в версії 3.13: Raise `TypeError` instead of `ValueError` for invalid keyword arguments.

somenamedtuple._fields

  Кортеж рядків із переліком імен полів. Корисно для самоаналізу та для створення нових іменованих типів кортежів із існуючих іменованих кортежів.

      >>> p._fields            # view the field names
      ('x', 'y')

      >>> Color = namedtuple('Color', 'red green blue')
      >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
      >>> Pixel(11, 22, 128, 255, 0)
      Pixel(x=11, y=22, red=128, green=255, blue=0)

somenamedtuple._field_defaults

  Словник зіставляє назви полів зі значеннями за замовчуванням.

      >>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
      >>> Account._field_defaults
      {'balance': 0}
      >>> Account('premium')
      Account(type='premium', balance=0)

Щоб отримати поле, ім’я якого зберігається в рядку, використовуйте функцію `getattr()`:

    >>> getattr(p, 'x')
    11

Щоб перетворити словник на іменований кортеж, використовуйте оператор подвійної зірочки (як описано в Розпакування списків аргументів):

    >>> d = {'x': 11, 'y': 22}
    >>> Point(**d)
    Point(x=11, y=22)

Оскільки іменований кортеж є звичайним класом Python, його легко додати або змінити функціональність за допомогою підкласу. Ось як додати обчислюване поле та формат друку з фіксованою шириною:

    >>> class Point(namedtuple('Point', ['x', 'y'])):
    ...     __slots__ = ()
    ...     @property
    ...     def hypot(self):
    ...         return (self.x ** 2 + self.y ** 2) ** 0.5
    ...     def __str__(self):
    ...         return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

    >>> for p in Point(3, 4), Point(14, 5/7):
    ...     print(p)
    Point: x= 3.000  y= 4.000  hypot= 5.000
    Point: x=14.000  y= 0.714  hypot=14.018

Показаний вище підклас встановлює `__slots__` на порожній кортеж. Це допомагає підтримувати низькі вимоги до пам’яті, запобігаючи створенню словників примірників.

Підкласи не корисні для додавання нових збережених полів. Замість цього просто створіть новий іменований тип кортежу з атрибута `_fields`:

    >>> Point3D = namedtuple('Point3D', Point._fields + ('z',))

Рядки документів можна налаштувати шляхом прямого призначення полів `__doc__`:

    >>> Book = namedtuple('Book', ['id', 'title', 'authors'])
    >>> Book.__doc__ += ': Hardcover book in active collection'
    >>> Book.id.__doc__ = '13-digit ISBN'
    >>> Book.title.__doc__ = 'Title of first printing'
    >>> Book.authors.__doc__ = 'List of authors sorted by last name'

Змінено в версії 3.5: Документаційні рядки властивостей стали доступними для запису.

Дивись також

- Дивіться `typing.NamedTuple`, щоб дізнатися, як додати підказки типу для іменованих кортежів. Він також забезпечує елегантну нотацію за допомогою ключового слова `class`:

      class Component(NamedTuple):
          part_number: int
          weight: float
          description: Optional[str] = None

- Перегляньте `types.SimpleNamespace()` для змінного простору імен, заснованого на базовому словнику замість кортежу.

- Модуль `dataclasses` надає декоратор і функції для автоматичного додавання згенерованих спеціальних методів до визначених користувачем класів.

## `OrderedDict` об’єкти

Упорядковані словники схожі на звичайні словники, але мають деякі додаткові можливості, пов’язані з операціями впорядкування. Тепер вони стали менш важливими, оскільки вбудований клас `dict` отримав можливість запам’ятовувати порядок вставки (ця нова поведінка стала гарантованою в Python 3.7).

Деякі відмінності від `dict` все ще залишаються:

- Звичайний `dict` був розроблений, щоб дуже добре виконувати операції відображення. Відстеження порядку вставки було другорядним.

- `OrderedDict` був розроблений, щоб добре справлятися з операціями зміни порядку. Ефективність простору, швидкість ітерації та продуктивність операцій оновлення були другорядними.

- Алгоритм `OrderedDict` може виконувати часті операції зміни порядку краще, ніж `dict`. Як показано в наведених нижче рецептах, це робить його придатним для реалізації різних видів кешів LRU.

- Операція рівності для `OrderedDict` перевіряє відповідність порядку.

  Звичайний `dict` може емулювати чутливий до порядку тест рівності з `p == q і all(k1 == k2 для k1, k2 в zip(p, q))`.

- Метод `popitem()` `OrderedDict` має інший підпис. Він приймає необов’язковий аргумент, щоб вказати, який елемент витягується.

  Звичайний `dict` може емулювати OrderedDict `od.popitem(last=True)` за допомогою `d.popitem()`, який гарантовано відкриває крайній правий (останній) елемент.

  Звичайний `dict` може емулювати OrderedDict `od.popitem(last=False)` з `(k := next(iter(d)), d.pop(k))`, який повертатиме і видаліть крайній лівий (перший) елемент, якщо він існує.

- `OrderedDict` має метод `move_to_end()` для ефективного переміщення елемента в кінцеву точку.

  Звичайний `dict` може емулювати OrderedDict `od.move_to_end(k, last=True)` з `d[k] = d.pop(k)`, який переміщуватиме ключ і його пов’язане значення до крайньої правої (останньої) позиції.

  Звичайний `dict` не має ефективного еквівалента для OrderedDict `od.move_to_end(k, last=False)`, який переміщує ключ і пов’язане з ним значення в крайню ліву (першу) позицію.

- До Python 3.8 `dict` не мав методу `__reversed__()`.

class collections.OrderedDict([items])

  Повертає екземпляр підкласу `dict`, який має спеціалізовані методи для зміни порядку словника.

  Added in version 3.1.

  popitem(last=True)

    Метод `popitem()` для впорядкованих словників повертає та видаляє пару (ключ, значення). Пари повертаються в порядку LIFO, якщо останній має значення true, або FIFO, якщо значення false.

  move_to_end(key, last=True)

    Перемістіть наявний ключ у будь-який кінець упорядкованого словника. Елемент переміщується в правий кінець, якщо last має значення true (за замовчуванням), або на початок, якщо last має значення false. Викликає `KeyError`, якщо ключ не існує:

        >>> d = OrderedDict.fromkeys('abcde')
        >>> d.move_to_end('b')
        >>> ''.join(d)
        'acdeb'
        >>> d.move_to_end('b', last=False)
        >>> ''.join(d)
        'bacde'

    Added in version 3.2.

На додаток до звичайних методів відображення, упорядковані словники також підтримують зворотну ітерацію за допомогою `reversed()`.

Equality tests between `OrderedDict` objects are order-sensitive and are roughly equivalent to `list(od1.items())==list(od2.items())`.

Equality tests between `OrderedDict` objects and other `Mapping` objects are order-insensitive like regular dictionaries. This allows `OrderedDict` objects to be substituted anywhere a regular dictionary is used.

Змінено в версії 3.5: Елементи, ключі та значення views `OrderedDict` тепер підтримують зворотну ітерацію за допомогою `reversed()`.

Змінено в версії 3.6: З прийняттям PEP 468 зберігається порядок для аргументів ключових слів, які передаються конструктору `OrderedDict` і його методу `update()`.

Змінено в версії 3.9: Додано оператори злиття (`|`) і оновлення (`|=`), указані в PEP 584.

### `OrderedDict` Приклади та рецепти

Легко створити впорядкований варіант словника, який запам’ятовує порядок останнього введення ключів. Якщо новий запис перезаписує існуючий запис, початкова позиція вставки змінюється та переміщується в кінець:

    class LastUpdatedOrderedDict(OrderedDict):
        'Store items in the order the keys were last added'

        def __setitem__(self, key, value):
            super().__setitem__(key, value)
            self.move_to_end(key)

`OrderedDict` також буде корисним для реалізації варіантів `functools.lru_cache()`:

    from collections import OrderedDict
    from time import time

    class TimeBoundedLRU:
        "LRU Cache that invalidates and refreshes old entries."

        def __init__(self, func, maxsize=128, maxage=30):
            self.cache = OrderedDict()      # { args : (timestamp, result)}
            self.func = func
            self.maxsize = maxsize
            self.maxage = maxage

        def __call__(self, *args):
            if args in self.cache:
                self.cache.move_to_end(args)
                timestamp, result = self.cache[args]
                if time() - timestamp <= self.maxage:
                    return result
            result = self.func(*args)
            self.cache[args] = time(), result
            if len(self.cache) > self.maxsize:
                self.cache.popitem(last=False)
            return result

    class MultiHitLRUCache:
        """ LRU cache that defers caching a result until
            it has been requested multiple times.

            To avoid flushing the LRU cache with one-time requests,
            we don't cache until a request has been made more than once.

        """

        def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1):
            self.requests = OrderedDict()   # { uncached_key : request_count }
            self.cache = OrderedDict()      # { cached_key : function_result }
            self.func = func
            self.maxrequests = maxrequests  # max number of uncached requests
            self.maxsize = maxsize          # max number of stored return values
            self.cache_after = cache_after

        def __call__(self, *args):
            if args in self.cache:
                self.cache.move_to_end(args)
                return self.cache[args]
            result = self.func(*args)
            self.requests[args] = self.requests.get(args, 0) + 1
            if self.requests[args] <= self.cache_after:
                self.requests.move_to_end(args)
                if len(self.requests) > self.maxrequests:
                    self.requests.popitem(last=False)
            else:
                self.requests.pop(args, None)
                self.cache[args] = result
                if len(self.cache) > self.maxsize:
                    self.cache.popitem(last=False)
            return result

## `UserDict` об’єкти

Клас `UserDict` діє як оболонка навколо об’єктів словника. Потреба в цьому класі була частково витіснена можливістю створювати підклас безпосередньо з `dict`; однак з цим класом може бути легше працювати, оскільки базовий словник доступний як атрибут.

class collections.UserDict([initialdata])

  Клас, який імітує словник. Вміст екземпляра зберігається у звичайному словнику, який доступний через атрибут `data` екземплярів `UserDict`. Якщо надано initialdata, `data` ініціалізується його вмістом; зауважте, що посилання на ініціальні дані не буде збережено, що дозволить використовувати його для інших цілей.

  На додаток до підтримки методів і операцій зіставлення, екземпляри `UserDict` забезпечують такий атрибут:

  data

    Справжній словник, який використовується для зберігання вмісту класу `UserDict`.

## `UserList` об’єкти

Цей клас діє як оболонка навколо об’єктів списку. Це корисний базовий клас для ваших власних спископодібних класів, які можуть успадковувати їх і перевизначати існуючі методи або додавати нові. Таким чином можна додавати нові моделі поведінки до списків.

Потреба в цьому класі була частково витіснена можливістю створювати підкласи безпосередньо з `list`; однак з цим класом може бути легше працювати, оскільки базовий список доступний як атрибут.

class collections.UserList([list])

  Клас, що імітує список. Вміст екземпляра зберігається у звичайному списку, який доступний через атрибут `data` екземплярів `UserList`. Вміст екземпляра спочатку встановлено як копія списку, за замовчуванням — порожній список `[]`. list може бути будь-яким ітерованим, наприклад справжнім списком Python або об’єктом `UserList`.

  На додаток до підтримки методів і операцій змінних послідовностей, екземпляри `UserList` забезпечують такий атрибут:

  data

    Справжній об’єкт `list`, який використовується для зберігання вмісту класу `UserList`.

Вимоги до підкласів: Очікується, що підкласи `UserList` пропонуватимуть конструктор, який можна викликати без аргументів або з одним аргументом. Список операцій, які повертають нову послідовність, намагається створити екземпляр фактичного класу реалізації. Для цього передбачається, що конструктор можна викликати за допомогою одного параметра, який є об’єктом послідовності, що використовується як джерело даних.

Якщо похідний клас не бажає відповідати цій вимозі, всі спеціальні методи, підтримувані цим класом, повинні бути перевизначені; будь ласка, зверніться до джерел для отримання інформації про методи, які необхідно надати в такому випадку.

## `UserString` об’єкти

Клас `UserString` діє як оболонка навколо рядкових об’єктів. Потреба в цьому класі була частково витіснена можливістю створювати підклас безпосередньо з `str`; однак з цим класом може бути легше працювати, оскільки базовий рядок доступний як атрибут.

class collections.UserString(seq)

  Клас, який імітує рядковий об’єкт. Вміст екземпляра зберігається у звичайному рядковому об’єкті, який доступний через атрибут `data` екземплярів `UserString`. Для вмісту екземпляра спочатку встановлено копію seq. Аргументом seq може бути будь-який об’єкт, який можна перетворити на рядок за допомогою вбудованої функції `str()`.

  На додаток до підтримки методів і операцій із рядками, екземпляри `UserString` надають такий атрибут:

  data

    Справжній об’єкт `str`, який використовується для зберігання вмісту класу `UserString`.

  Змінено в версії 3.5: Нові методи `__getnewargs__`, `__rmod__`, `casefold`, `format_map`, `isprintable` і `maketrans`.