Есть ли способ defaultdict(defaultdict(int))
, чтобы заставить следующий код работать?
for x in stuff:
d[x.a][x.b] += x.c_int
d
должен быть построен Ad-Hoc, в зависимости от x.a
и x.b
элементов.
Я мог бы использовать:
for x in stuff:
d[x.a,x.b] += x.c_int
но тогда я не смог бы использовать:
d.keys()
d[x.a].keys()
python
collections
Джонатан
источник
источник
Ответы:
Да, вот так:
Аргумент a
defaultdict
(в данном случаеlambda: defaultdict(int)
) вызывается при попытке доступа к ключу, который не существует. Его возвращаемое значение будет установлено как новое значение этого ключа, что означает, что в нашем случае значениеd[Key_doesnt_exist]
будетdefaultdict(int)
.При попытке доступа к ключу от этого последнего defaultdict то
d[Key_doesnt_exist][Key_doesnt_exist]
она возвращает 0, что возвращаемое значение аргумента последней defaultdict тоint()
.источник
defaultdict
(в данном случаеlambda : defaultdict(int)
) будет вызван, когда вы попытаетесь получить доступ к ключу, который не существует, и его возвращаемое значение будет установлено как новое значение этого ключа, которое означает в в нашем случае значениеd[Key_dont_exist]
будет равноdefaultdict(int)
, и если вы попытаетесь получить доступ к ключу из этого последнего defaultdict, т.е.d[Key_dont_exist][Key_dont_exist]
он вернет 0, что является возвращаемым значением аргумента последнего,defaultdict
т. е.int()
надеюсь, что это было полезно.defaultdict
должен быть функцией.defaultdict(int)
это словарь, аlambda: defaultdict(int)
функция, которая возвращает словарь.defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
Параметром конструктора defaultdict является функция, которая будет вызываться для создания новых элементов. Так что давайте использовать лямбду!
Начиная с Python 2.7, есть еще лучшее решение с использованием Counter :
Некоторые бонусы
Для получения дополнительной информации см. PyMOTW - Коллекции - Типы данных контейнера и Документация Python - коллекции
источник
d = defaultdict(lambda : Counter())
а неd = defaultdict(lambda : defaultdict(int))
специально для решения проблемы, как первоначально поставлено.d = defaultdict(Counter())
не использовать лямбдуCounter
объект вместо объекта. То есть:d = defaultdict(Counter)
Я нахожу это немного более элегантным для использования
partial
:Конечно, это то же самое, что лямбда.
источник
Для справки, можно реализовать общий вложенный
defaultdict
метод фабрики через:Глубина определяет количество вложенных словарей перед использованием типа, определенного в
default_factory
. Например:источник
ndd = nested_defaultdict(dict) .... ndd['a']['b']['c']['d'] = 'e'
броскиKeyError: 'b'
depth=0
, который не всегда может быть желательным, если глубина неизвестна во время вызова. Легко исправить, добавив строкуif not depth: return default_factory()
вверху функции, хотя, возможно, есть более элегантное решение.В предыдущих ответах говорилось, как сделать два уровня или n уровней
defaultdict
. В некоторых случаях вы хотите бесконечный:Использование:
источник
Другие правильно ответили на ваш вопрос о том, как заставить работать следующее:
Альтернативой будет использование кортежей для ключей:
Преимущество этого подхода в том, что он прост и может быть легко расширен. Если вам нужно отображение глубиной в три уровня, просто используйте кортеж из трех предметов для ключа.
источник