Python имеет тысячи сторонних библиотек, но вы знали, что наиболее мощные инструменты уже включены в стандартную библиотеку?

Эта серия посвящена 'Углубленному изучению стандартной библиотеки Python', мы собираемся поочередно разобрать стандартную библиотеку, которая часто используется, но не была глубоко рассмотрена.

Цель состоит не в простом перечислении функций, а в том, чтобы освоить концепции на основе практических примеров и развить ваши навыки применения кода, что поможет вам повысить уровень использования Python.


Углубленное использование collections: от основ до практического применения

1. Почему начинать с collections

collections предлагает очень эффективные расширенные коллекции, которые дополняют встроенные типы данных Python (list, dict, tuple) с точки зрения производительности и структуры. Эти коллекции часто встречаются на практике, но глубоко не рассматриваются.

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


2. Counter – эталон для подсчета частоты и больше

Count all the things!

Основная концепция

collections.Counter – это один из очень полезных классов, содержащихся в стандартной библиотеке Python, модуле collections. Это специальный словарь, оптимизированный для подсчета частоты появления данных.

from collections import Counter

c = Counter(['a', 'b', 'c', 'a', 'b', 'a'])
print(c)  # Counter({'a': 3, 'b': 2, 'c': 1})

Это структура данных, которая подсчитывает, сколько раз каждый элемент появляется в итерируемом объекте (iterable), таком как списки, строки, кортежи и словари.


Основные функции и методы

📌 Разнообразные способы инициализации

Counter можно инициализировать разными способами, что позволяет гибко анализировать данные.

from collections import Counter

print(Counter(['a', 'b', 'a']))
# Counter({'a': 2, 'b': 1}) → список

print(Counter({'a': 2, 'b': 1}))
# Counter({'a': 2, 'b': 1}) → словарь

print(Counter(a=2, b=1))
# Counter({'a': 2, 'b': 1}) → ключевые аргументы

📌 Доступ к элементам

Counter работает как dict, но когда вы обращаетесь к несуществующему ключу, он возвращает 0 вместо KeyError.

c = Counter('hello')
print(c['l'])  # 2 (символ 'l' появляется 2 раза)
print(c['x'])  # 0 ('x' не было, но возвращается 0 вместо ошибки)

📌 Добавление/изменение элементов

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

c = Counter('hello')
c['l'] += 3
print(c)
# Counter({'l': 5, 'o': 1, 'h': 1, 'e': 1})

📌 most_common(n) – извлечение наиболее часто встречающихся элементов

Возвращает список кортежей n элементов, отсортированных по убыванию частоты появления.

c = Counter('banana')
print(c.most_common(2))
# [('a', 3), ('n', 2)] → 'a' появляется 3 раза, 'n' – 2 раза

📌 elements() – итератор, который перебирает элементы

Предоставляет итератор, который перебирает элементы на основе значений счетчика.

c = Counter('banana')
print(list(c.elements()))
# ['b', 'a', 'a', 'a', 'n', 'n']

Однако элементы со значением 0 и ниже не будут включены.


📌 Поддержка математических операций (+, -, &, | между Counter)

Counter имеет одно из ключевых преимуществ по сравнению со словарями – поддерживает арифметические и множественные операции.

c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)

print(c1 + c2)
# Counter({'a': 4, 'b': 3}) → одинаковые ключи объединяются

print(c1 - c2)
# Counter({'a': 2}) → отрицательные значения игнорируются, ключ 'b' исключен

print(c1 & c2)
# Counter({'a': 1, 'b': 1}) → пересечение, минимальные значения

print(c1 | c2)
# Counter({'a': 3, 'b': 2}) → объединение, максимальные значения

Примеры практического использования

📌 Анализ слов в строках
text = "the quick brown fox jumps over the lazy dog"
counter = Counter(text.split())
print(counter)
📌 Анализ частоты логов
logs = ['INFO', 'ERROR', 'INFO', 'DEBUG', 'ERROR', 'ERROR']
print(Counter(logs))  # Counter({'ERROR': 3, 'INFO': 2, 'DEBUG': 1})
📌 Подсчет дубликатов в списках
nums = [1, 2, 2, 3, 3, 3]
print(Counter(nums))  # Counter({3: 3, 2: 2, 1: 1})

На что стоит обратить внимание

  • Counter наследуется от dict, но не гарантирует сортировку. Если порядок важен, следует использовать most_common().
  • Элементы не будут удалены, даже если их значение оказывается равным 0 или меньше, поэтому может потребоваться фильтрация.
c = Counter(a=3)
c.subtract({'a': 5})
print(c)  # Counter({'a': -2})  # Обратите внимание, что элементы не исчезают, даже если значение меньше или равно 0

Совет: как накапливать без инициализации

counter = Counter()
with open("data.txt") as f:
    for line in f:
        counter.update(line.strip().split())

Итоги

collections.Counter – это мощный инструмент, который незаменим для анализа данных, обработки логов и текстового майнинга. Для начинающих он служит простым инструментом для подсчета частоты, а для опытных пользователей может эволюционировать в сложный инструмент обработки с комбинированием операций и фильтрации.


Анонс следующей части

  • defaultdict – мир без KeyError, еще более гибкий, чем dict! Ожидайте следующую часть!

Углубленное понимание стандартной библиотеки и ее правильное использование непременно повысят качество вашего кода.