Введение в модуль Collections в Python

Коллекции в Python – это контейнеры, которые используются для хранения коллекций данных, например list, dict, set, tuple и т.д. Это встроенные коллекции. Было разработано несколько модулей, которые предоставляют дополнительные структуры данных для хранения коллекций данных. Одним из таких является модуль Collections в Python.

Модуль Collections в Python был представлен для улучшения функциональности встроенных контейнеров коллекции. Collections был впервые представлен в версии 2.4. Это руководство основано на его последней стабильной версии (версия 3.7).

Модуль Collections

В этом руководстве мы обсудим 6 наиболее часто используемых структур данных из модуля коллекций Python:

  • Counter;
  • defaultdict;
  • OrderedDict;
  • deque;
  • ChainMap;
  • namedtuple().

Counter

Counter – это подкласс объекта словаря. Функция Counter() в модуле коллекций принимает в качестве аргумента итерацию или отображение и возвращает словарь. В этом словаре ключ – это элемент в итерируемом объекте или отображении, а значение – это количество раз, которое элемент существует в итерируемом объекте или отображении.

Перед созданием экземпляра счетчика необходимо импортировать класс Counter.

from collections import Counter

Как создать объекты?

Есть несколько способов создания объектов счетчика. Самый простой способ – использовать функцию Counter() без аргументов.

cnt = Counter()

Вы можете передать итерацию (список) в функцию Counter(), чтобы создать объект счетчика.

list = [1,2,3,4,1,2,6,7,3,8,1]
Counter(list)

Наконец, функция Counter() может принимать словарь в качестве аргумента. В этом словаре значение ключа должно быть «счетчиком» этого ключа.

Counter({1:3,2:4})

Вы можете получить доступ к любому элементу счетчика с его ключом, как показано ниже:

list = [1,2,3,4,1,2,6,7,3,8,1]
cnt = Counter(list)
print(cnt[1])

Когда вы напечатаете cnt [1], вы получите счет 1.

Вывод:

3

В приведенных выше примерах cnt – это объект класса Counter, который является подклассом dict. Итак, в нем есть все методы класса dict.

Кроме того, Counter имеет три дополнительных функции:

  1. Elements;
  2. Most_common ([n]);
  3. Subtract ([interable-or-mapping]).
Функция element()

Вы можете получить элементы объекта Counter с помощью функции elements(). Он возвращает список, содержащий все элементы объекта Counter.

Взгляните на следующий пример:

cnt = Counter({1:3,2:4})
print(list(cnt.elements()))

Вывод:

[1, 1, 1, 2, 2, 2, 2]

Здесь мы создаем объект Counter со словарем в качестве аргумента. В этом объекте Counter счетчик 1 равен 3, а счетчик 2 равен 4. Функция elements() вызывается с использованием объекта cnt, который возвращает итератор, который передается в качестве аргумента в список.

Итератор повторяет 3 раза в течение 1, возвращая три ‘1’, и повторяется четыре раза для 2, возвращая в список четыре ‘2’. Наконец, список распечатывается с помощью функции печати.

Функция most_common()

Функция Counter() возвращает неупорядоченный словарь. Вы можете отсортировать его по количеству отсчетов в каждом элементе, используя функцию most_common() объекта Counter.

list = [1,2,3,4,1,2,6,7,3,8,1]
cnt = Counter(list)
print(cnt.most_common())

Вывод:

[(1, 3), (2, 2), (3, 2), (4, 1), (6, 1), (7, 1), (8, 1)]

Вы можете видеть, что функция most_common возвращает список, который отсортирован по количеству элементов. 1 имеет счетчик три, поэтому это первый элемент списка.

Функция subtract()

Subtract() принимает в качестве аргумента итерацию (список) или отображение (словарь) и вычитает количество элементов, используя этот аргумент. Посмотрите следующий пример:

cnt = Counter({1:3,2:4})
deduct = {1:1, 2:2}
cnt.subtract(deduct)
print(cnt)

Вывод:

Counter({1: 2, 2: 2})

Вы можете заметить, что объект cnt, который мы создали первым, имеет счетчик 3 для «1» и счетчик 4 для «2». Словарь вычитания имеет значение «1» для ключа «1» и значение «2» для ключа «2». Функция subtract() вычитала 1 отсчет из клавиши «1» и 2 отсчета из клавиши «2».

Defaultdict

Defaultdict работает точно так же, как словарь Python, за исключением того, что он не генерирует KeyError при попытке доступа к несуществующему ключу.

Вместо этого он инициализирует ключ элементом того типа данных, который вы передаете в качестве аргумента при создании defaultdict. Тип данных называется default_factory.

Как импортировать defaultdict?

Во-первых, вы должны импортировать defaultdict из модуля коллекций перед его использованием:

from collections import defaultdict

Как создать defaultdict?

Вы можете создать defaultdict с помощью конструктора defaultdict(). Вы должны указать тип данных в качестве аргумента. Проверьте следующий код:

nums = defaultdict(int)
nums['one'] = 1
nums['two'] = 2
print(nums['three'])

Вывод:

0

В этом примере int передается как default_factory. Обратите внимание, что вы передаете только int, а не int(). Затем значения определяются для двух ключей, а именно «один» и «два», но в следующей строке мы пытаемся получить доступ к ключу, который еще не был определен.

В обычном словаре это вызовет KeyError. Но defaultdict инициализирует новый ключ значением default_factory по умолчанию, равным 0 для int. Следовательно, когда программа будет выполнена, будет напечатан 0. Эта особенность инициализации несуществующих ключей может использоваться в различных ситуациях.

Например, предположим, что вы хотите подсчитать каждое имя в списке имен, указанном как «Майк, Джон, Майк, Анна, Майк, Джон, Джон, Майк, Майк, Бритни, Смит, Анна, Смит».

from collections import defaultdict

count = defaultdict(int)
names_list = "Mike John Mike Anna Mike John John Mike Mike Britney Smith Anna Smith".split()
for names in names_list:
    count[names] +=1
print(count)

Вывод:

defaultdict(<class 'int'>, {'Mike': 5, 'Britney': 1, 'John': 3, 'Smith': 2, 'Anna': 2})

Сначала мы создаем defaultdict с int, как default_factory. В список names_list входит набор имен, которые повторяются несколько раз. Функция split() возвращает список из заданной строки. Он разбивает строку всякий раз, когда встречается пробел, и возвращает слова как элементы списка. В цикле каждый элемент в списке добавляется к defaultdict с именем count и инициализируется значением 0 на основе default_factory. Если тот же элемент встречается снова, по мере продолжения цикла, счетчик этого элемента будет увеличиваться.

OrderedDict

OrderedDict – это словарь, в котором ключи сохраняют порядок, в котором они вставляются, что означает, что если вы измените значение ключа позже, он не изменит положение ключа.

Как импортировать OrderedDict?

Чтобы использовать OrderedDict, вам необходимо импортировать его из модуля коллекций.

from collections import OrderedDict

Как создать OrderedDict?

Вы можете создать объект OrderedDict с конструктором OrderedDict(). В следующем коде вы создаете OrderedDict без каких-либо аргументов. После этого в него вставляются какие-то предметы.

od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
print(od)

Вывод:

OrderedDict([('a', 1), ('b', 2), ('c', 3)])

Вы также можете получить доступ к каждому элементу с помощью цикла. Взгляните на следующий код:

for key, value in od.items():
    print(key, value)

Вывод:

a 1
b 2
c 3

Следующий пример представляет собой интересный вариант использования OrderedDict с Counter. Здесь мы создаем Counter из списка и вставляем элемент в OrderedDict на основе их количества.

Наиболее часто встречающаяся буква будет вставлена в качестве первого ключа, а наименее часто встречающаяся буква будет вставлена в качестве последнего ключа.

list = ["a","c","c","a","b","a","a","b","c"]
cnt = Counter(list)
od = OrderedDict(cnt.most_common())
for key, value in od.items():
    print(key, value)

Вывод:

a 4
c 3
b 2

deque

deque – это список, оптимизированный для вставки и удаления элементов.

Импорт deque

Перед использованием необходимо импортировать класс deque из модуля коллекций.

from collections import deque

Создание deque

Вы можете создать двухстороннюю очередь с конструктором deque(). Вы должны передать список в качестве аргумента.

list = ["a","b","c"]
deq = deque(list)
print(deq)

Вывод:

deque(['a', 'b', 'c'])

Вставка элементов в deque

Вы можете легко вставить элемент в deq, который мы создали на любом из концов. Чтобы добавить элемент справа от двухсторонней очереди, вы должны использовать метод append().

Если вы хотите добавить элемент в начало двухсторонней очереди, вы должны использовать метод appendleft().

deq.append("d")
deq.appendleft("e")
print(deq)deque

Вывод:

deque(['e', 'a', 'b', 'c', 'd'])

Вы можете заметить, что d добавляется в конце deq, а e добавляется в начало deq.

Удаление элементов из двухсторонней очереди

Удаление элементов аналогично вставке элементов. Вы можете удалить элемент так же, как вставляете элементы. Чтобы удалить элемент с правого конца, вы можете использовать функцию pop(), а чтобы удалить элемент с левого края, вы можете использовать popleft().

deq.pop()
deq.popleft()
print(deq)

Вывод:

deque(['a', 'b', 'c'])

Вы можете заметить, что и первый, и последний элементы удалены из deq.

Очистка двухсторонней очереди

Если вы хотите удалить все элементы из двухсторонней очереди, вы можете использовать функцию clear().

list = ["a","b","c"]
deq = deque(list)
print(deq)
print(deq.clear())

Вывод:

deque(['a', 'b', 'c'])
None

Как видно на выходе, сначала идет очередь из трех элементов. Как только мы применили функцию clear(), двухсторонняя очередь очищается, и вы не видите ничего на выходе.

Подсчет элементов в двухсторонней очереди

Если вы хотите узнать количество определенного элемента, используйте функцию count (x). Вы должны указать элемент, для которого вам нужно найти счетчик, в качестве аргумента.

list = ["a","b","c"]
deq = deque(list)
print(deq.count("a"))

Вывод:

1

В приведенном выше примере количество «а» равно 1. Следовательно, напечатано «1».

ChainMap

ChainMap используется для объединения нескольких словарей или отображений, возвращает список словарей.

Как импортировать?

Перед использованием необходимо импортировать ChainMap из модуля коллекций.

from collections import ChainMap
Как создать?

Для создания карты мы можем использовать конструктор ChainMap(). Мы должны передать словари, которые мы собираемся объединить, в качестве набора аргументов.

dict1 = { 'a' : 1, 'b' : 2 }
dict2 = { 'c' : 3, 'b' : 4 }
chain_map = ChainMap(dict1, dict2)
print(chain_map.maps)

Вывод:

[{'b': 2, 'a': 1}, {'c': 3, 'b': 4}]

В качестве вывода вы можете увидеть список словарей. Вы можете получить доступ к значениям карты последовательности по имени ключа.

print(chain_map['a'])

Вывод:

1

«1» печатается, поскольку значение ключа «a» равно 1. Другой важный момент – ChainMap обновляет свои значения при обновлении связанных с ней словарей. Например, если вы измените значение «c» в dict2 на «5», вы также заметите изменение в ChainMap.

dict2['c'] = 5
print(chain_map.maps)

Вывод:

[{'a': 1, 'b': 2}, {'c': 5, 'b': 4}]

Получение ключей и значений

Вы можете получить доступ к клавишам ChainMap с помощью функции keys(). Точно так же вы можете получить доступ к значениям элементов с помощью функции values(), как показано ниже:

dict1 = { 'a' : 1, 'b' : 2 }
dict2 = { 'c' : 3, 'b' : 4 }
chain_map = ChainMap(dict1, dict2)
print (list(chain_map.keys()))
print (list(chain_map.values()))

Вывод:

['b', 'a', 'c']
[2, 1, 3]

Обратите внимание, что значение ключа ‘b’ в выводе является значением ключа ‘b’ в dict1. Как правило, когда один ключ появляется в нескольких связанных словарях, ChainMap берет значение этого ключа из первого словаря.

Добавление нового словаря

Если вы хотите добавить новый словарь к существующей ChainMap, используйте функцию new_child(). Он создает новую ChainMap с недавно добавленным словарем.

dict3 = {'e' : 5, 'f' : 6}
new_chain_map = chain_map.new_child(dict3)
print(new_chain_map)

Вывод:

ChainMap({'f': 6, 'e': 5}, {'a': 1, 'b': 2}, {'b': 4, 'c': 3})

Обратите внимание, что новый словарь добавлен в начало списка ChainMap.

Namedtuple()

Namedtuple() возвращает кортеж с именами для каждой позиции в кортеже. Одна из самых больших проблем с обычными кортежами заключается в том, что вы должны помнить индекс каждого поля объекта кортежа. Очевидно, это сложно. Для решения этой проблемы был введен namedtuple.

Как импортировать?

Перед использованием namedtuple необходимо импортировать его из модуля collections.

from collections import namedtuple

Как создать?

from collections import namedtuple

Student = namedtuple('Student', 'fname, lname, age')
s1 = Student('John', 'Clarke', '13')
print(s1.fname)

Вывод:

Student(fname='John', lname='Clarke', age='13')

В этом примере объявлен объект namedtuple Student. Вы можете получить доступ к полям любого экземпляра класса Student по заданному имени поля.

Создание с помощью списка

Функция namedtuple() требует, чтобы каждое значение передавалось ей отдельно. Вместо этого вы можете использовать _make() для создания экземпляра namedtuple со списком. Проверьте следующий код:

s2 = Student._make(['Adam','joe','18'])
print(s2)

Вывод:

Student(fname='Adam', lname='joe', age='18')

Создание нового экземпляра

Функцию _asdict() можно использовать для создания экземпляра OrderedDict из существующего экземпляра.

s2 = s1._asdict()
print(s2)

Вывод:

OrderedDict([('fname', 'John'), ('lname', 'Clarke'), ('age', '13')])
Изменение значений полей с помощью функции _replace()

Чтобы изменить значение поля экземпляра, используется функция _replace(). Помните, что функция _replace() создает новый экземпляр. Это не меняет значение существующего экземпляра.

s2 = s1._replace(age='14')
print(s1)
print(s2)

Вывод:

Student(fname='John', lname='Clarke', age='13')
Student(fname='John', lname='Clarke', age='14')

Заключение

На этом мы завершаем наше руководство по модулю collections в Python, который все еще нуждается в улучшениях, если мы сравним его с библиотекой Java Collection.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *