Python — подробная библиотека инструментов для коллекций

Python

Эта статья возникла из личного публичного аккаунта:TechFlow, оригинальность это не просто, прошу внимания


Сегодня я представлю полезную и базовую библиотеку инструментов в Python, называемую коллекциями.

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


defaultdict


Можно сказать, что defaultdict является самым простым в использовании в этой библиотеке, и его определение также очень простое, мы можем в основном увидеть это из названия. Это решает наиболее распространенную проблему, когда мы используем dict, а именноключ пустСлучай.

В обычных обстоятельствах, когда мы получаем элементы в dict, нам нужно рассмотреть случай, когда ключ пуст. Если это не учитывать, то при получении несуществующего ключа система выкинет исключение. Конечно, мы можем написать суждение if перед каждым get, но это очень хлопотно, например:

if key in dict:
    return dict[key]
else:
    return None

Конечно, это самый тупой метод, dict предоставляет намсо значением по умолчаниюполучить метод. Например, мы можем написать:

return dict.get(key, None)

Таким образом, когда ключ не существует в словаре, он автоматически вернется к установленному нами значению по умолчанию. Это избавляет от многих хлопотных суждений, но в некоторых особых случаях все еще остается небольшая проблема. Например, когда ключ дублируется, мы хотим сохранить одно и то же значение ключа в списке, а не только одно. В этом случае код будет сложнее написать:

data = [(1, 3), (2, 1), (1, 4), (2, 5), (3, 7)]
d = {}
for k, v in data:
    if k in d:
        d[k].append(v)
    else:
        d[k] = [v]

Поскольку значением dict является список, нам все равно нужно судить, пусто ли оно, и мы не можем напрямую использовать значение по умолчанию.Конечно, косвенная операция возможна, но она все же недостаточно проста:

for k, v in data:
    cur = d.get(k, [])
    cur.append(v)
    d[k] = v

Это мало чем отличается от использования if.Чтобы идеально решить эту проблему, мы можем использоватьdefaultdict:

from collections import defaultdict
d = defaultdict(list)

for k, v in data:
    d[k].append(v)

После использования defaultdict, если ключ не существует, контейнер автоматически вернется к нашему предустановленному значению по умолчанию. Следует отметить, что значение по умолчанию, передаваемое через defaultdict, может бытьТип также может быть методом. Если мы передаем int, значение по умолчанию будет установлено на результат int(), который равен 0. Если мы хотим настроить или изменить его, мы можем передать метод, например:

d = defaultdict(lambda: 3)

for k, v in data:
    d[k] += v

Counter


Это очень распространенный и очень мощный инструмент, который мы часто используем.

В нашем реальном программировании мы часто сталкиваемся с проблемой, т.Считать и сортировать. Например, когда мы анализируем текст, мы получим кучу слов. Может быть большое количество длинных слов, которые могут встречаться в тексте всего несколько раз. Итак, мы хотим подсчитать количество вхождений этих слов и оставить только те, которые встречаются чаще всего.

Конечно, нам несложно реализовать это требование самостоятельно, мы можем создать дикт и потом по этим словам проходить по ним. Изначально нам также необходимо рассмотреть ситуацию, когда слово не встречалось ранее, если мы упомянули выше defaultdict, это будет намного проще. Но нам все еще нужен шаг подсчета и сортировки, если мы используем Counter, то этот шаг уменьшится до одной строки кода.

Например:

words = ['apple', 'apple', 'pear', 'watermelon', 'pear', 'peach']
from collections import Counter
counter = Counter(words)

>>> print(counter)

Counter({'apple': 2, 'pear': 2, 'watermelon': 1, 'peach': 1})

Мы напрямую передаем список в Counter в качестве параметра, и он автоматически подсчитывает каждый элемент для нас.

Если мы хотим отфильтровать topK, это тоже очень просто, он предоставляет нам метод most_common, нам нужно только передать нужное нам K:

counter.most_common(1)

[('apple', 2)]

В дополнение к этому его конструктор также принимает тип dict. Мы можем инициализировать Counter непосредственно через dict, значение которого имеет тип int, например:

c = Counter({'apple': 5, 'pear': 4})
c = Counter(apple=4, pear=3)

Кроме того, он поддерживаетСложение и вычитаниеНапример, мы можем добавить два Счетчика, он автоматически объединит два Счетчика, и будут накапливаться значения, соответствующие одному и тому же ключу. То же самое верно и для вычитания.Соответствующее значение будет вычтено.Ключ, который не соответствует вычитаемому ключу, будет сохранен, а ключ, который не может совпасть при вычитании, будет отброшен. И следует отметить, что Counter поддерживает отрицательные значения.


deque


Все мы знаем, что очередь — это очередь, и дека — тоже очередь, но она немного особенная, дадека. Для очереди разрешено вставлять элементы только в конец очереди и извлекать элементы в начало очереди. Поскольку deque называется двусторонней очередью, это означает, что и начало, и конец очереди поддерживают вставку и извлечение элементов. По сравнению с обычными очередями она более гибкая.

В дополнение к часто используемым API-интерфейсам, таким как очистка, копирование, подсчет и расширение, наиболее часто используемые и основные API-интерфейсы в deque — это append, pop, appendleft и popleft. Из названия видно, что append и pop и list append и pop — это одно и то же, а appendleft и popleft находятся в очереди.левый, то есть головка выполняет операции извлечения и добавления. Очень легко понять.

В повседневном использовании не так много алгоритмов, которые действительно используют двусторонние очереди. В большинстве случаев мы используем deque по двум основным причинам: во-первых, deque управляется GIL, т.е.потокобезопасностьиз. Список, с другой стороны, не имеет блокировки GIL, поэтому он не является потокобезопасным. Другими словами, в параллельных сценариях list может вызвать проблемы с согласованностью, а deque — нет. Другая причина - декаПоддерживается фиксированная длина, когда длина заполнена, когда мы продолжим добавление, автоматически появятся самые ранние вставленные данные.

Например, когда у нас есть большой объем данных, мы не знаем его объем, но хотим сохранить последний указанный объем данных, мы можем использовать deque.

from collections import deque
dque = deque(maxlen=10)
# 假设我们想要从文件当中获取最后10条数据
for i in f.read():
    dque.append(i)

namedtuple


namedtuple особенный, он включает в себяметапрограммированиеКонцепция чего-либо. Краткое введение в понятие метапрограммирования, не будем слишком углубляться. Короче, в общем объектно-ориентированный. Мы все определяем классы, а затем создаем экземпляры через конструктор класса. Метапрограммирование означает, что мы определяем метакласс, и то, что создается из метакласса, является не экземпляром, а классом. Если форма и готовое изделие используются для описания класса и экземпляра соответственно, метакласс эквивалентенплесень плесень.

namedtuple — это очень простой метакласс, с помощью которого мы можем очень удобно определять нужные нам классы.

Его использование очень простое, давайте сразу к примеру. Например, если мы хотим определить класс учащихся, который имеет три поля имени, оценки и возраста, то этот класс будет записан как:

class Student:
    def __init__(self, name=None, score=None, age=None):
        self.name = name
        self.score = score
        self.age = age

Это просто грубый способ написания.Если вы рассматриваете спецификацию, вам нужно определить аннотации, такие как свойство, и вам понадобится много кода. Это можно упростить, если использовать namedtuple, давайте посмотрим на код:

from collections import namedtuple
# 这个是类,columns也可以写成'name score age',即用空格分开
Student = namedtuple('Student', ['name', 'score', 'age'])

# 这个是实例
student = Student(name='xiaoming', score=99, age=10)
print(student.name)

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

Student = namedtuple('Student', ['name', 'score', 'age'], defaults=(0, 0))

Обратите внимание, что хотя мы определили три поля, мы установили только два отсутствующих значения. В этом случае namedtuple автоматически сопоставит отсутствующие значения с полями score и age. Поскольку в спецификации PythonОбязательные параметры должны предшествовать необязательным параметрам. Таким образом, nuamdtuple автоматически выравнивается по правому краю.

Подробно наша сегодняшняя статья представила использование четырех структур данных defaultdict, Counter, deque и namedtuple. В дополнение к этим четырем в библиотеке коллекций есть еще несколько классов инструментов, но частота нашего использования немного ниже, и из-за недостатка места мы не будем здесь вдаваться в подробности. Заинтересованные учащиеся могут самостоятельно просматривать соответствующие API и документы.

На сегодняшней статье все. Если вы чувствуете, что что-то приобрели, пожалуйста, отсканируйте код и нажмитеобрати внимание наЧто ж, твое маленькое усилие много значит для меня.