November 3, 2024

defaultdict в Python

Что еще за defaultdict и зачем нам еще один dict? Давайте об этом и поговорим в статье.

Что такое defaultdict


Это подкласс встроенного класса dict, который вызывает фабричную функцию, позволяющую задать дефолтное значение для новых / несуществующих ключей. Во всем остальном он схож с уже знакомым нам dict.
Если упростить и вывести термин, опираясь на название, то получается, что это просто словарь с значениями по умолчанию.

Синтаксис

from collections import defaultdict

defaultdict(default_factory=None, /, [...]) --> dict with default factory


Аргументы Первый аргумент предоставляет начальное значение для атрибута default_factory, которое по умолчанию равно None. Все остальные аргументы обрабатываются так же, как если бы они были переданы конструктору dict.

Пара слов про метод __missing__() Если аргумент default_factory != None, то этот метод и вызывается для предоставления значений по умолчанию, когда запрошенный ключ не найден.

Чтобы в полной мере понять происходящее, давайте рассмотрим несколько примеров.

Примеры. Какие проблемы решает defaultdict

Получаем нужное нам значение по умолчанию

Давайте создадим 2 словаря: 1 - dict, другой - defaultdict и попробуем получить значения для существующих ключей:

from collections import defaultdict  
  
dict_1 = {"first": 1, "second": 2}  
dict_2 = defaultdict(int, first=1, second=2)

print(dict_1["first"])  # 1
print(dict_2["first"])  # 1

В обоих случаях получим 1.

А что, если запросить значение для несуществующего ключа:

print(dict_1["missing_key"])  # KeyError: 'missing_key'
print(dict_2["missing_key"])  # 0

В первом случае мы получили исключение KeyError, а вот уже с defaultdict мы получили значение по умолчанию: 0.

Можно ли обойти эту ситуацию с помощью dict? Да, можно. Например, так:

print(dict_1.get("missing_key", 0))  # 0

Здесь мы явно задали значение по умолчанию в виде 0, если не получится найти ключ.

Идем дальше.

Считаем количество слов в списке

Допустим, у нас есть список из слов list_1 и надо посчитать, сколько раз каждое слово встречается в списке, затем вывести все это в формате словаря.
Как сделать это удобно? Конечно с defaultdict!

from collections import defaultdict  

list_1 = ["building", "thee", "sun", "python", "sun", "python", "python", "thee", "python"] 

# 1.
result = defaultdict(int)   

# 2.
for word in list_1:
    result[word] += 1

# 3.
print(dict(result))  # {'building': 1, 'thee': 2, 'sun': 2, 'python': 4}

Что здесь происходит? 1. Мы инициализируем defaultdict классом int для того, чтобы для каждого нового слова было задано значение по умолчанию = 0.
2. Проходимся по всем словам из списка list_1.
- Если слово не встречалось ранее, в result создается новая пара ключ-значение, где ключ - слово, а значение - 0, после чего оно сразу увеличивается на 1.
- Если слово уже есть в словаре, то его значение просто увеличивается на 1.
3. Печатаем наш результат, предварительно преобразовав наш defaultdict в обычный dict.

В результате получаем нужный нам ответ: {'building': 1, 'thee': 2, 'sun': 2, 'python': 4}.

Делаем выводы


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

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