Создание словарных клавиш на лету

Работа с глубоко вложенными питонами python, я хотел бы иметь возможность назначать значения в такой структуре данных, как это:

  mydict[key][subkey][subkey2]="value"

без необходимости проверять, что mydict [key] и т.д. фактически заданы как dict, например. используя

  if not key in mydict: mydict[key]={}

Создание подзаголовков должно происходить "на лету". Какой самый элегантный способ позволить нечто эквивалентное - возможно, используя декораторы на стандартном <type 'dict'>?

Ответ 1

class D(dict):
    def __missing__(self, key):
        self[key] = D()
        return self[key]

d = D()
d['a']['b']['c'] = 3

Ответ 2

Вы можете использовать кортеж в качестве ключа для dict, а затем вам вообще не нужно беспокоиться о поддиректориях:

mydict[(key,subkey,subkey2)] = "value"

В качестве альтернативы, если вам действительно нужно иметь подзаголовки по какой-то причине, вы можете использовать collections.defaultdict.

Для двух уровней это просто:

>>> from collections import defaultdict
>>> d = defaultdict(dict)
>>> d['key']['subkey'] = 'value'
>>> d['key']['subkey']
'value'

В три раза несколько сложнее:

>>> d = defaultdict(lambda: defaultdict(dict))
>>> d['key']['subkey']['subkey2'] = 'value'
>>> d['key']['subkey']['subkey2']
'value'

Четыре и более уровней остаются в качестве упражнения для читателя.: -)

Ответ 3

Мне нравится, что Дэйв лучше отвечает, но вот альтернатива.

from collections import defaultdict
d = defaultdict(lambda : defaultdict(int))
>>> d['a']['b'] += 1
>>> d
defaultdict(<function <lambda> at 0x652f0>, {'a': defaultdict(<type 'int'>, {'b': 1})})
>>> d['a']['b']
1

http://tumble.philadams.net/post/85269428/python-nested-defaultdicts

Это определенно не очень удобно использовать lambdas для реализации внутренних дефолтных коллекций, но, по-видимому, необходимо.