Python collections — Counter, defaultdict, OrderedDict

17 июля 2026
Автор

Антон Ларичев

Модуль collections в Python

Python поставляется с мощным стандартным модулем collections, который расширяет возможности встроенных типов данных. Три наиболее часто используемых класса из этого модуля — Counter, defaultdict и OrderedDict — решают конкретные задачи, с которыми регулярно сталкиваются разработчики.

Counter — подсчёт элементов

Counter — это подкласс dict, предназначенный для подсчёта частоты элементов в итерируемом объекте. Он позволяет избежать ручного написания цикла с условной проверкой.

Создание Counter

from collections import Counter

# Из строки
char_count = Counter("hello world")
print(char_count)
# Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})

# Из списка
fruits = Counter(["apple", "banana", "apple", "cherry", "banana", "apple"])
print(fruits)
# Counter({'apple': 3, 'banana': 2, 'cherry': 1})

# Из словаря
scores = Counter({"alice": 5, "bob": 3, "charlie": 5})
print(scores)
# Counter({'alice': 5, 'charlie': 5, 'bob': 3})

# С именованными аргументами
votes = Counter(python=10, javascript=8, typescript=6)
print(votes)
# Counter({'python': 10, 'javascript': 8, 'typescript': 6})

Основные методы Counter

from collections import Counter

words = Counter(["python", "java", "python", "go", "python", "java", "rust"])

# most_common(n) — n наиболее частых элементов
print(words.most_common(2))
# [('python', 3), ('java', 2)]

# most_common() без аргумента — все элементы, отсортированные по частоте
print(words.most_common())
# [('python', 3), ('java', 2), ('go', 1), ('rust', 1)]

# elements() — итерация с повторением согласно счётчику
print(list(words.elements()))
# ['python', 'python', 'python', 'java', 'java', 'go', 'rust']

# subtract() — вычитание счётчиков
other = Counter(["python", "java"])
words.subtract(other)
print(words)
# Counter({'python': 2, 'go': 1, 'rust': 1, 'java': 1})

# update() — добавление к счётчику
words.update(["go", "go"])
print(words)
# Counter({'go': 3, 'python': 2, 'java': 1, 'rust': 1})

Арифметика с Counter

Counter поддерживает математические операции между счётчиками:

from collections import Counter

a = Counter(python=4, java=2, go=1)
b = Counter(python=1, java=3, rust=2)

# Сложение — объединение с суммированием
print(a + b)
# Counter({'python': 5, 'java': 5, 'rust': 2, 'go': 1})

# Вычитание — только положительные результаты
print(a - b)
# Counter({'python': 3, 'go': 1})

# Пересечение — минимальные значения
print(a & b)
# Counter({'java': 2, 'python': 1})

# Объединение — максимальные значения
print(a | b)
# Counter({'python': 4, 'java': 3, 'rust': 2, 'go': 1})

Практические примеры с Counter

Анализ частоты слов в тексте:

from collections import Counter
import re

text = """
Python — высокоуровневый язык программирования общего назначения.
Python широко используется в анализе данных, веб-разработке
и машинном обучении. Python прост в изучении.
"""

words = re.findall(r'\b[а-яёА-ЯЁa-zA-Z]+\b', text.lower())
word_count = Counter(words)

print("Топ-5 слов:")
for word, count in word_count.most_common(5):
    print(f"  {word}: {count}")

Проверка анаграмм:

from collections import Counter

def are_anagrams(word1: str, word2: str) -> bool:
    return Counter(word1.lower()) == Counter(word2.lower())

print(are_anagrams("listen", "silent"))  # True
print(are_anagrams("hello", "world"))    # False

# Версия без учёта пробелов
def are_anagrams_clean(word1: str, word2: str) -> bool:
    clean = lambda s: Counter(s.lower().replace(" ", ""))
    return clean(word1) == clean(word2)

print(are_anagrams_clean("Astronomer", "Moon starer"))  # True

defaultdict — словарь с дефолтным значением

defaultdict — подкласс dict, который не выбрасывает KeyError при обращении к несуществующему ключу, а автоматически создаёт его с дефолтным значением через переданную фабричную функцию.

Проблема, которую решает defaultdict

Без defaultdict группировка элементов выглядит громоздко:

# Без defaultdict
students = [("alice", "math"), ("bob", "physics"), ("alice", "physics"), ("charlie", "math")]

groups = {}
for student, subject in students:
    if student not in groups:
        groups[student] = []
    groups[student].append(subject)

print(groups)
# {'alice': ['math', 'physics'], 'bob': ['physics'], 'charlie': ['math']}

С defaultdict код становится чище:

from collections import defaultdict

students = [("alice", "math"), ("bob", "physics"), ("alice", "physics"), ("charlie", "math")]

groups = defaultdict(list)
for student, subject in students:
    groups[student].append(subject)

print(dict(groups))
# {'alice': ['math', 'physics'], 'bob': ['physics'], 'charlie': ['math']}

Типы фабричных функций

from collections import defaultdict

# int — для счётчиков (дефолт 0)
word_count = defaultdict(int)
for word in ["python", "java", "python", "go"]:
    word_count[word] += 1
print(dict(word_count))
# {'python': 2, 'java': 1, 'go': 1}

# list — для группировки
grouped = defaultdict(list)
for key, value in [("a", 1), ("b", 2), ("a", 3)]:
    grouped[key].append(value)
print(dict(grouped))
# {'a': [1, 3], 'b': [2]}

# set — для уникальных значений
unique_values = defaultdict(set)
for key, value in [("a", 1), ("b", 2), ("a", 1), ("a", 3)]:
    unique_values[key].add(value)
print(dict(unique_values))
# {'a': {1, 3}, 'b': {2}}

# lambda — произвольное дефолтное значение
config = defaultdict(lambda: "N/A")
config["host"] = "localhost"
print(config["host"])   # localhost
print(config["port"])   # N/A

Вложенные defaultdict

from collections import defaultdict

# Двухуровневый defaultdict — матрица смежности графа
graph = defaultdict(lambda: defaultdict(int))

graph["A"]["B"] += 1
graph["A"]["C"] += 2
graph["B"]["C"] += 1

for node, edges in graph.items():
    for neighbor, weight in edges.items():
        print(f"{node} -> {neighbor}: {weight}")
# A -> B: 1
# A -> C: 2
# B -> C: 1

Практический пример — инвертированный индекс

from collections import defaultdict

documents = {
    1: "python programming language",
    2: "java programming tutorial",
    3: "python tutorial for beginners",
    4: "advanced python programming",
}

inverted_index = defaultdict(list)

for doc_id, text in documents.items():
    for word in text.split():
        inverted_index[word].append(doc_id)

def search(query: str) -> list:
    results = set()
    for word in query.split():
        results.update(inverted_index.get(word, []))
    return sorted(results)

print(search("python"))          # [1, 3, 4]
print(search("programming"))     # [1, 2, 4]
print(search("python tutorial")) # [1, 2, 3, 4]

OrderedDict — словарь с сохранением порядка

OrderedDict — подкласс dict, который гарантирует порядок вставки ключей и предоставляет дополнительные методы для управления им. Начиная с Python 3.7 обычные словари тоже сохраняют порядок вставки, однако OrderedDict остаётся полезным благодаря уникальным возможностям.

Создание и базовое использование

from collections import OrderedDict

od = OrderedDict()
od["first"] = 1
od["second"] = 2
od["third"] = 3

for key, value in od.items():
    print(f"{key}: {value}")
# first: 1
# second: 2
# third: 3

# Создание из списка пар
od2 = OrderedDict([("x", 10), ("y", 20), ("z", 30)])
print(od2)
# OrderedDict([('x', 10), ('y', 20), ('z', 30)])

Уникальные возможности OrderedDict

from collections import OrderedDict

od = OrderedDict([("a", 1), ("b", 2), ("c", 3), ("d", 4)])

# move_to_end() — перемещение ключа в конец
od.move_to_end("b")
print(list(od.keys()))
# ['a', 'c', 'd', 'b']

# move_to_end(last=False) — перемещение в начало
od.move_to_end("d", last=False)
print(list(od.keys()))
# ['d', 'a', 'c', 'b']

# popitem() — удаление последнего элемента (LIFO)
last = od.popitem()
print(last)  # ('b', 2)

# popitem(last=False) — удаление первого элемента (FIFO)
first = od.popitem(last=False)
print(first)  # ('d', 4)

print(list(od.keys()))
# ['a', 'c']

Сравнение с учётом порядка

Ключевое отличие OrderedDict от обычного dict — учёт порядка при сравнении:

from collections import OrderedDict

# Обычные dict — порядок не важен
d1 = {"a": 1, "b": 2}
d2 = {"b": 2, "a": 1}
print(d1 == d2)  # True

# OrderedDict — порядок важен
od1 = OrderedDict([("a", 1), ("b", 2)])
od2 = OrderedDict([("b", 2), ("a", 1)])
print(od1 == od2)  # False

# При сравнении OrderedDict с dict порядок не учитывается
d3 = {"a": 1, "b": 2}
od3 = OrderedDict([("b", 2), ("a", 1)])
print(d3 == od3)  # True

Практический пример — LRU Cache

OrderedDict идеально подходит для реализации кэша с вытеснением давно неиспользуемых элементов:

from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.cache = OrderedDict()

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        # Перемещаем в конец — элемент недавно использовался
        self.cache.move_to_end(key)
        return self.cache[key]

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            self.cache.move_to_end(key)
        self.cache[key] = value
        if len(self.cache) > self.capacity:
            # Удаляем самый давно неиспользуемый элемент (первый)
            self.cache.popitem(last=False)

    def __repr__(self) -> str:
        return f"LRUCache({dict(self.cache)})"


cache = LRUCache(3)
cache.put(1, "one")
cache.put(2, "two")
cache.put(3, "three")
print(cache)  # LRUCache({1: 'one', 2: 'two', 3: 'three'})

cache.get(1)         # ключ 1 перемещается в конец
cache.put(4, "four") # вытесняем самый старый — ключ 2
print(cache)  # LRUCache({3: 'three', 1: 'one', 4: 'four'})

Комбинирование инструментов

Классы из collections хорошо работают вместе. Пример — анализ логов с группировкой по пользователю и подсчётом частоты эндпоинтов:

from collections import Counter, defaultdict

logs = [
    ("alice", "/api/users"),
    ("bob", "/api/products"),
    ("alice", "/api/users"),
    ("alice", "/api/orders"),
    ("bob", "/api/users"),
    ("charlie", "/api/products"),
]

# defaultdict(Counter) — группируем по пользователю, считаем эндпоинты
user_stats = defaultdict(Counter)

for user, endpoint in logs:
    user_stats[user][endpoint] += 1

for user, endpoints in user_stats.items():
    print(f"\n{user}:")
    for endpoint, count in endpoints.most_common():
        print(f"  {endpoint}: {count}")

# alice:
#   /api/users: 2
#   /api/orders: 1
# bob:
#   /api/products: 1
#   /api/users: 1
# charlie:
#   /api/products: 1

Выбор нужного инструмента

Задача Инструмент
Подсчёт частоты элементов Counter
Поиск топ-N элементов Counter.most_common()
Сравнение двух наборов данных Counter (арифметика)
Группировка данных по ключу defaultdict(list)
Счётчик без проверки KeyError defaultdict(int)
Сбор уникальных значений по ключу defaultdict(set)
Кэш с гарантированным порядком OrderedDict
LRU-кэш OrderedDict
Сравнение словарей с учётом порядка OrderedDict

Модуль collections — это часть стандартной библиотеки Python, не требующая дополнительной установки. Знание его инструментов позволяет писать более идиоматичный и эффективный код: Counter избавляет от ручных счётчиков, defaultdict убирает лишние проверки при группировке, а OrderedDict решает задачи, где критичен порядок ключей.

Чтобы уверенно использовать все возможности Python — от стандартной библиотеки до продвинутых паттернов — изучите полный курс по Python на PurpleSchool: https://purpleschool.ru/course/python?utm_source=knowledgebase&utm_medium=text&utm_campaign=python-collections

Стрелочка влевоTypedDict в Python: типизированные словари

Постройте личный план изучения Python до уровня Middle — бесплатно!

Python — часть карты развития Backend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Все гайды по Python

Как отправлять запросы с помощью requests в PythonПочему Python выводит значение без команды printКак работает команда print в PythonВозможности Python для автоматизации задачРабота с JSON в Python на примерахPython get — методы получения данныхКак находить и исправлять ошибки в PythonРабота с данными через API и внешние сервисыСтруктура и оформление кода PythonОсновы Django с PythonПолезные приёмы в Python для повседневной работыИспользование locals в Python для отладкиИнтеграция PHP и PythonКак выполнять HTTPS-запросы в PythonFastAPI Python — быстрый старт: создание REST API с нуляКак работать с API в Python
Ввод целого числа в PythonВедение логов в PythonУдаление данных в Python с помощью removeОбработка исключений с помощью try/except в PythonФункция super() в Python — как вызвать метод родителяСоздание собственных контекстных менеджеров в PythonРабота с символами программирования PythonРабота с переменной X в PythonРабота с классами в PythonКак скачать Python на компьютерПростая программа на Python для начинающихОсновы Python для тех, кто начинаетЧто нового в Python 3Поддерживается ли Python 2 и стоит ли его использоватьPython 1 — с чего начиналась история языкаКоманда python print - полное руководство по выводу данныхПравила именования переменных в PythonПользовательские исключения в PythonОсновы Python coreОписание объектов PythonНаследование классов в Python — основы и примерыМножественное наследование в Python — примеры и MROКонтекстный менеджер with в Python — как работает и зачем нуженКомментарии в Python — однострочные, многострочные и docstringКакой Python выбрать для установкиКак вывести целое число с помощью print в PythonКак установить Python на Windows macOS и LinuxКак пользоваться консолью PythonКак получить последний элемент в PythonКак найти значение в PythonКак настроить PythonКак использовать print для строк в PythonКак работает интерпретатор PythonИнструкция по работе с PythonБлок finally в обработке исключений PythonЦелые числа в PythonАбстрактные классы в Python — ABC и abstractmethod
Pydantic: валидация данных в Python
Загрузка данных PythonУправление проектами на GitHub с PythonСоздание веб-приложений на Flask PythonСоздание бота на PythonСоздание интерфейсов Python QTСоздание игр с PygameСоздание GUI в PythonКак работать со словарями в PythonРабота с библиотеками через Python PackagingРабота со временем в Python при помощи модуля timePython name — особенности переменнойМатематические операции в Python с модулем mathPython listing — что это и как использоватьPytest — тестирование на Python: полное руководствоОбработка изображений с OpenCV PythonNumPy в Python — основы и применение в задачахМашинное обучение с PythonИспользование Anaconda с PythonМодуль contextlib в Python — утилиты для контекстных менеджеровБиблиотеки Python и их применение в проектах
Возврат значений из функции в PythonВложенные функции в PythonСоздание собственных декораторов в PythonРабота с функцией map в PythonЦикл while в Python и примеры использованияОбработка чисел, введённых через input в PythonОсновные операторы в Python с примерамиУсловные выражения if else в Python для начинающихКак выполняется вызов функций call в PythonПродвинутые генераторы в Python — send, throw, close и корутиныПозиционные и именованные аргументы в PythonОбъявление переменных и управление областью видимости в PythonПередача аргументов по ссылке и по значению в PythonПередача аргументов через args и kwargs в PythonОсновные методы Python и примеры их использованияОператор match/case в Python 3.10+ — основы структурного сопоставленияПаттерны match/case в Python — деструктуризация, guard и вложенные шаблоныПрактические примеры match/case в Python — реальные сценарии примененияЛокальные и глобальные переменные в PythonЧасто используемые команды PythonКлючевые слова global и nonlocal в PythonКак создавать функции в PythonКак работает сборщик мусора в PythonКак работает область видимости переменных в PythonКак работает функция callable в PythonКак работает функция any и all в PythonКак проверить тип переменной в PythonКак передать функцию как аргумент в PythonКак использовать функцию isinstance в PythonКак использовать функцию filter в PythonКак использовать функцию filter в PythonКак использовать функцию eval безопасно в PythonКак использовать декораторы в PythonИзменяемые и неизменяемые типы данных в PythonГенераторы и yield в Python — как создавать и использоватьГенераторные выражения в Python — синтаксис и примерыФункции в Python и способы их вызоваФункции как объекты в PythonЧто такое замыкания в PythonЧто делает функция reduce в PythonЧто делает функция id в PythonАргументы по умолчанию в PythonАнонимные функции и lambda в PythonАлгоритмы на Python — примеры и объяснение
Запись данных в PythonУстановка pip в PythonУправление зависимостями requirement в PythonУправление библиотеками с помощью Python PackagingУдаление пробелов с помощью strip в PythonСтруктурирование кода в PythonСоздание исполняемого файла Python в exeРазбор traceback в модуле PythonРазбор site-packages в PythonРазбор Program Files в PythonРабота с Unicode кодировками в PythonРабота с системными функциями Python sysРабота с папкой AppData в PythonРабота с модулем logging в PythonРабота с каталогами в PythonРабота с CSV в PythonВиртуальная среда venv в Python — создание и настройкаКак создать простое приложение на PythonИспользование pip в Python для установки пакетовМодули в Python и организация кода в проектеИмпорт модулей в Python и правила подключенияРабота с файлами в Python пошаговоЧто делает компилятор Python и как он работаетПолучение строки из модуля PythonПодключение файлов в Python с includeПеременные среды в PythonСборка проекта с помощью packaging в PythonНастройка Python сервераИспользование Python на UbuntuИспользование консоли PythonИспользование кодировок в PythonИнициализация пакетов PythonИмпорт модулей PythonИмпорт имен в PythonСреда IDLE Python и базовые возможностиЧтение и запись TXT в PythonЧтение файлов в Python с помощью open file
Удаление элементов из списка PythonТипы данных в Python — обзор и рекомендацииОсновные операции со строками в PythonМетоды str в Python и обработка текстаСписки в Python и их ключевые методыСоздание списков данных в PythonРабота со строками и символами в PythonРабота со столбцами в PythonРабота со списком значений в PythonРабота с таблицами в Python с помощью DataFrameРабота с RFR в PythonРабота с пробелами в PythonРабота с массивами в PythonРабота с кортежами tuple PythonРабота с координатами X и Y в PythonРабота с ключами в PythonРабота с элементами данных PythonРабота с двоичными числами PythonРабота с данными в PythonРабота с данными NumPy PythonРабота с большими числами в PythonРабота с битами в PythonРабота с байтами в PythonЧто такое значение в Python и как его определитьМножества в Python и операции с нимиИспользование range в Python для цикловПроверка на четность в PythonПроверка числа в PythonПреобразование типов в PythonПреобразование списка в строку PythonПреобразование числа в строку в PythonПостроение графиков в PythonОпределение индекса элемента в PythonОкругление чисел в PythonОбъединение списков в Python с помощью zipМножества в PythonМассивы в Python и отличие от списковМассив чисел в PythonКортежи данных в PythonКак вычислить сумму чисел в PythonКак получить остаток от деления в PythonКак найти следующее число в PythonИспользование Unicode в PythonТип int в Python и его особенностиИндекс списка в PythonФункции для работы со строками в PythonЭлементы Python и способы доступа к нимДоступ к элементам массива в PythonДеление чисел в PythonРабота с данными в Python на практикеКак работать с числами в Python
Открыть базу знаний

Лучшие курсы по теме

Иконка молнииНовый
изображение курса

Основы Python

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий