Преимущества использования словаря collections.defaultdict()

Опубликован: 22.01.2024 83

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

В частности, модуль collections предоставляет усовершенствованный вариант словаря defaultdict(), который всегда возвращает значение по умолчанию при обращении к несуществующему ключу.

Синтаксис: collections.defaultdict( default_factory=None [, ...] )

  • default_factory - первый аргумент представляет тип данных (str, int, list и т.п.) или функцию, которая возвращает значение по умолчанию для новых значений словаря (по умолчанию default_factory равен None);
  • `[, ...] - все остальные аргументы являются элементами словаря и обрабатываются так же, как если бы они были переданы конструктору dict().

Словарь collections.defaultdict() является подклассом встроенного класса dict() с одним переопределенным методом __missing__(key) и одной доступной для записи переменной экземпляра класса default_factory. Остальная функциональность такая же, как и для класса dict().

Использование словаря collections.defaultdict() вместо обычного словаря имеет как минимум два преимущества:

  • во-первых, полностью исключается появление ошибки KeyError, возникающей при обращении к несуществующему ключу словаря или при вводе новых значений;
  • во-вторых, использование defaultdict() делает код проще и быстрее, чем при использовании эквивалентного метода обычного словаря dict.setdefault(), так как при инициализации разных значений по разным ключам каждый раз передается значение по умолчанию (это позволяет хранить по разным ключам даже разные типы данных).
from collections import defaultdict

# использование функции int в качестве default_factory 
d_int = defaultdict(int)
d_int['a']
0         # создается словарь {'a': 0} со значением по умолчанию 0

# инициализация разных значений по разным ключам
d_int['a'] += 5
d_int['b'] = d_int['c'] + 10
d_int      # вывод словаря
defaultdict(<class 'int'>, {'a': 5, 'c': 0, 'b': 10})

# использование функции str в качестве default_factory
d_str = defaultdict(str)
d_str['a']            # инициализация нового значения {'a': ''}
''
d_str['b'] += 'apple'    # инициализация нового значения {'b': 'apple'}
d_str['b']
'apple'     
d_str['list_a'] = [1, 2, 3]   # инициализация нового значения {'list_a': [1, 2, 3]}
d_str         # вывод словаря
defaultdict(<class 'str'>, {'a': '', 'b': 'apple', 'list_a': [1, 2, 3]})

# использование функции list в качестве default_factory
d_list = defaultdict(list)
d_list['a']
[]          # создается словарь {'a': []} со значением [] пустой список

# в качестве default_factory можно использовать функцию lambda
d = defaultdict(lambda: '[default_value]')
d['a']
'[default_value]'   # создается словарь {'a': [default_value]}

Примеры использования defaultdict().

Предположим, что необходимо посчитать сколько раз было использовано каждое слово в предложении.

# Для этого можно использовать или обычный словарь `dict()`:
text = "ДЛЯ ТОГО, ЧТОБЫ ЗНАТЬ, ЧТО НРАВСТВЕННО, НАДО ЗНАТЬ, ЧТО БЕЗНРАВСТВЕННО; ДЛЯ ТОГО, ЧТОБЫ ЗНАТЬ, ЧТО ДЕЛАТЬ, НАДО ЗНАТЬ, ЧЕГО НЕ ДОЛЖНО ДЕЛАТЬ."
words = text.split()

reg_dict = dict()
for word in words:
    if word in reg_dict:
        reg_dict[word] += 1
    else:
        reg_dict[word] = 1

print(reg_dict)
{'ДЛЯ': 2, 'ТОГО,': 2, 'ЧТОБЫ': 2, 'ЗНАТЬ,': 4, 'ЧТО': 3, 'НРАВСТВЕННО,': 1, 'НАДО': 2, 'БЕЗНРАВСТВЕННО;': 1, 'ДЕЛАТЬ,': 1, 'ЧЕГО': 1, 'НЕ': 1, 'ДОЛЖНО': 1, 'ДЕЛАТЬ.': 1}

# или словарь `defaultdict()`:
from collections import defaultdict

d = defaultdict(int)
for word in words:
    d[word] += 1

print(d)
defaultdict(<class 'int'>, {'ДЛЯ': 2, 'ТОГО,': 2, 'ЧТОБЫ': 2, 'ЗНАТЬ,': 4, 'ЧТО': 3, 'НРАВСТВЕННО,': 1, 'НАДО': 2, 'БЕЗНРАВСТВЕННО;': 1, 'ДЕЛАТЬ,': 1, 'ЧЕГО': 1, 'НЕ': 1, 'ДОЛЖНО': 1, 'ДЕЛАТЬ.': 1})

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

Похожие посты

Преимущества двухсторонней очереди collections.deque() над списком

Использование collections.namedtuple() для создания неизменяемого словаря

Количество одинаковых элементов в списке (кортеже) или строке

Методы преобразования списка в строку и обратно

Комментариев нет.