Модуль collections

контейнерные типы данных
Модуль включает контейнерные типы данных, которые не охватываются встроенными типами list, dict, tuple
Типы данных из Collections
ChainMap - класс объединяет словари в одну надструктуру

Counter - подкласс dict для подсчета объектов последовательности

OrderedDict - Добавлен подкласс dict, который запоминает порядок записи элементов

UserDict - оболочка вокруг объектов словаря для упрощения создания подклассов dict

UserList - оболочка вокруг объектов списка для упрощения создания подклассов списка

UserString - обертка вокруг строковых объектов для упрощения создания подклассов строк

namedtuple() - фабричная функция для создания кортежей с именованными полями

deque - двухсторонняя очередь

defaultdict - подкласс dict, который вызывает не вызывает исключение при обращении к отсутствующему ключу
namedtuple - именованный кортеж
Именованные кортежи делают код яснее – вместо индексирования составляющие объекта вызываются по явным именам. Рассматривать структуру лучше на примере
Именованный кортеж

from collections import namedtuple

User = namedtuple('User', ['first_name', 'last_name', 'age'])
user1 = User('Максим', 'Бекурин', 35)

print(user1)
#Вывод: User(first_name='Максим', last_name='Бекурин', age=35)

print(user1.first_name)
#Вывод: Максим
deque - двухсторонняя очередь
deque является усовершенствованным вариантом списка с оптимизированной вставкой/удалением элементов с обоих концов. Реализация deque оптимизирована так, что операции извлечения элементов слева и справа имеют примерно одинаковую производительность O(1). Добавление новых элементов в конец происходит не сильно медленнее, чем во встроенных списках, но добавление в начало выполняется существенно быстрее.

Добавление элемента в конец используется команда append(), в начало appendleft().
Для добавление итерируемого объекта (несколько элементов) используйте extend(iterable) и extendleft(iterable).
rotate(n=1) – последовательно переносит n элементов из начала в конец (если n отрицательно, то с конца в начало). В этом поведение deque напоминает кольцевой связный список.

Очередь deque имеет аргумент maxlen, позволяющий ограничить ее размер. При заполнении ограниченной очереди добавление n новых объектов «слева» вызовет удаление n элементов справа.
Добавление элементов

from collections import deque

seq = [1, 2, 3, 4, 5]
deq = deque(seq)
deq.append(6)      # добавление в конец
deq.appendleft(0)  # добавление в начало
print(deq)

#Вывод: deque([0, 1, 2, 3, 4, 5, 6])

deq.extend([7, 8, 9])      # добавление в конец
deq.extendleft([-1, -2, -3])  # добавление в начало
print(deq)

#Вывод: deque([-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Chainmap - связанные карты
Класс позволяет последовательно связывать словари, используя их в порядке указания. Поддерживаются все обычные методы словаря. Кроме того, есть атрибут maps , метод для создания новых подконтекстов и свойство для доступа ко всем сопоставлениям.

ChainMap объединяет словари. При этом получается не один общий словарь, а их совокупность, в которой каждый словарь остаётся независимой составляющей.

При обращении к ChainMap по ключу одного из словарей, происходит поиск значения среди всех словарей и выводит первое найденное.

При необходимости расширить составленный ранее ChainMap можно методом new_child()
Объединение словарей

from collections import ChainMap

letters = {'a': 1, 'b': 2}
vowels = {'a': 2, 'b': 0, 'c': 0, 'd': 0, 'e': 1}
chain = ChainMap(letters, vowels)

print(chain['b'])

# Вывод: 2
OrderedDict - словарь, который запоминает порядок записи элементов
Класс позволяет создавать словари, которые запоминают порядок записи элементов. Обычный dict был разработан, чтобы быть лучшим в операциях итерации и производительности работы. Отслеживание порядка вставки для него – дело вторичное. OrderDict использует приоритет порядок добавления записи элементов.

Класс имеет методы:
  • popitem(last=True) – удаляет последний элемент если last=True, и первый, если last=False
  • move_to_end(key, last=True) – переносит ключ key в конец, если last=True, и в начало, если last=False
Добавление элементов

from collections import OrderedDict

d = OrderedDict.fromkeys([])
d['Максим'] = 10
d['Владимир'] = 20
d['Иван'] = 30
print(d)
# Вывод: OrderedDict([('Максим', 10), ('Владимир', 20), ('Иван', 30)])

d.move_to_end('Максим')
print(d)
# Вывод: OrderedDict([('Владимир', 20), ('Иван', 30), ('Максим', 10)])

d.popitem(last=True)
print(d)
# Вывод: OrderedDict([('Владимир', 20), ('Иван', 30)])
Counter - счетчик объектов
Класс позволяет производить подсчет элементов в последовательностях. Функция принимает итерируемый аргумент и возвращает словарь, в котором ключами служат неповторяющиеся элементы, а значениями – количества вхождений элемента в переданную последовательность.

Если элемент отсутствует в последовательности, при обращении по ключу счётчик не вызовет исключение, а вернет нулевое значение.

Объекты Counter можно складывать и вычитать друг из друга. Также применять операнды ' & ' и ' | '
Подсчет возрастных групп

from collections import Counter

age = [32, 33, 34, 33, 45, 34, 45, 23, 32, 23, 45, 23, 21, 25, 45]
age_counter = Counter(age)
print(age_counter)

# Вывод: Counter({45: 4, 23: 3, 32: 2, 33: 2, 34: 2, 21: 1, 25: 1})
Метод elements() преобразует результаты подсчета в итератор

from collections import Counter

age_counter = Counter({45: 4, 23: 3, 32: 2, 33: 2, 34: 2, 21: 1, 25: 1})
age = list(age_counter.elements())
print(age)


# Вывод: [45, 45, 45, 45, 23, 23, 23, 32, 32, 33, 33, 34, 34, 21, 25]
Метод most_common(n) ищет n самых повторяющихся элементов

from collections import Counter

age = [32, 33, 34, 33, 45, 34, 45, 23, 32, 23, 45, 23, 21, 25, 45]
age_counter = Counter(age)
age_n2 = age_counter.most_common(2)
print(age_n3)

# Вывод: [(45, 4), (23, 3)]
уникальные значения, самые редкие элементы. Их можно найти срезом с шагом -1 (-2 и т. д.)

from collections import Counter

age = [32, 33, 34, 33, 45, 34, 45, 23, 32, 23, 45, 23, 21, 25, 45]
age_counter = Counter(age)
age_unique = age_counter.most_common()[-1:]
print(age_unique)


# Вывод: [(25, 1)]
defaultdict - словарь
Позволяет создавать словарь со значениями, которые встречаются в последовательности. При обращении к несуществующему ключу, создаст элемент с именем ключа словаря и пустым значением.
Формирование словаря из списка со значениями ключей

from collections import defaultdict

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

print(dict(d))


# Вывод: {'yellow': [1, 3], 'blue': [2, 4], 'red': [1]}