Вы можете использовать функции int(), list() или dict(), чтобы возвращать пустые значения по умолчанию: int() возвращает 0, list() возвращает пустой список ([]) и dict() возвращает пустой словарь ({}). Если вы опустите аргумент, исходное значение нового ключа будет равно None.
Кстати, вы можете использовать lambda для того, чтобы определить функцию по умолчанию изнутри вызова:
>>> bestiary = defaultdict(lambda: 'Huh?')
>>> bestiary['E']
'Huh?'
Применение int — это один из способов создать ваш собственный прилавок:
>>> from collections import defaultdict
>>> food_counter = defaultdict(int)
>>> for food in ['spam', 'spam', 'eggs', 'spam']:
…·····food_counter[food] += 1
…
>>> for food, count in food_counter.items():
…·····print(food, count)
…
eggs 1
spam 3
В предыдущем примере, если бы food_counter был обычным словарем, а не defaultdict, Python генерировал бы исключение всякий раз, когда бы мы пытались увеличить элемент словаря food_counter[food], поскольку он был бы не инициализирован. Нам понадобилось бы сделать дополнительную работу, как показано здесь:
>>> dict_counter = {}
>>> for food in ['spam', 'spam', 'eggs', 'spam']:
…·····if not food in dict_counter:
…·········dict_counter[food] = 0
…·····dict_counter[food] += 1
…
>>> for food, count in dict_counter.items():
…·····print(food, count)
…
spam 3
eggs 1
Если говорить о счетчиках, то в стандартной библиотеке имеется счетчик, который решает задачу, показанную в предыдущем примере, и даже больше:
>>> from collections import Counter
>>> breakfast = ['spam', 'spam', 'eggs', 'spam']
>>> breakfast_counter = Counter(breakfast)
>>> breakfast_counter
Counter({'spam': 3, 'eggs': 1})
Функция most_common() возвращает все элементы в убывающем порядке или лишь те элементы, количество которых больше, чем заданный аргумент count:
>>> breakfast_counter.most_common()
[('spam', 3), ('eggs', 1)]
>>> breakfast_counter.most_common(1)
[('spam', 3)]
Счетчики можно объединять. Для начала снова взглянем на содержимое breakfast_counter:
>>> breakfast_counter
>>> Counter({'spam': 3, 'eggs': 1})
Теперь мы создадим новый список, который называется lunch, и счетчик, который называется lunch_counter:
>>> lunch = ['eggs', 'eggs', 'bacon']
>>> lunch_counter = Counter(lunch)
>>> lunch_counter
Counter({'eggs': 2, 'bacon': 1})
Счетчики можно объединить с помощью оператора +:
>>> breakfast_counter + lunch_counter
Counter({'spam': 3, 'eggs': 3, 'bacon': 1})
Как вы можете догадаться, счетчики можно вычитать друг из друга с помощью оператора —. Что мы будем есть на завтрак, но не на обед?
>>> breakfast_counter — lunch_counter
Counter({'spam': 3})
О’кей, теперь узнаем, что мы можем съесть на обед, но не можем на завтрак:
>>> lunch_counter — breakfast_counter
Counter({'bacon': 1, 'eggs': 1})
По аналогии с множествами, показанными в главе 4, вы можете получить общие элементы с помощью оператора пересечения &:
>>> breakfast_counter & lunch_counter
Counter({'eggs': 1})
В результате пересечения был получен общий элемент ('eggs') с низким значением счетчика. Это имеет смысл: на завтрак у нас было только одно яйцо, поэтому указанное количество является общим.
Наконец, вы можете получить все элементы с помощью оператора объединения |:
>>> breakfast_counter | lunch_counter
Counter({'spam': 3, 'eggs': 2, 'bacon': 1})
Элемент 'eggs' снова оказался общим для обоих счетчиков. В отличие от сложения объединение не складывает счетчики, а выбирает тот, который имеет наибольшее значение.