简体   繁体   中英

Recursive collections.defaultdict initialization

My goal is to, given a python dict which I call datainit , create a recursive collections.defaultdict which I call data , such as data is initialised with datainit , and data can be extended with any path of missing keys, as illustrated below

from collections import *
datainit={'number':1}
data =something_with(defaultdict(), datainit)
data['A']['B']['C']=3
#At this stage, I want:
#data['A']['B']['C'] ==3
#data['number'] == 1
#and nothing else.

The normal way to do that starting with an empty dict is, for instance:

nested_dict = lambda: defaultdict(nested_dict)
data = nested_dict()

Trying:

nested_dict = lambda: defaultdict(nested_dict, datainit)
data = nested_dict()

Will logically result in my datainit being duplicated for each missing key:

>>> datainit={'number':1}
>>> nested_dict = lambda: defaultdict(nested_dict, datainit)
>>> data=nested_dict()
>>> data
defaultdict(<function <lambda> at 0x7f58e5323758>, {'number': 1})
>>> data['A']['B']['C']=2
>>> data
defaultdict(<function <lambda> at 0x7f58e5323758>, {'A': defaultdict(<function <lambda> at 0x7f58e5323758>, {'B': defaultdict(<function <lambda> at 0x7f58e5323758>, {'C': 2, 'number': 1}), 'number': 1}),
'number': 1})

All this makes sense, but how do I do to just start with an initial dict and then just use an empty dict for each missing keys? What should be my something_with(defaultdict(), datainit) .

Probably obvious, but I cannot see it!

You have two tiers; the top level defaultdict , which must have the number key, and a series of arbitrarily nested dictionaries, which must not. Your mistake is to try to treat these as one, and to try to treat 'number' as something the factory for missing values should handle.

Just set the number key in the top dictionary. There is just one such key, with a value, and it should not be handled by the defaultdict() factory. The factory is there to provide a default value for arbitrary missing keys, number is not an arbitrary key.

from collections import defaultdict

def topleveldict():
    nested_dict = lambda *a, **kw: defaultdict(nested_dict, *a, **kw)
    return nested_dict(number=1)  # or nested_dict({'number': 1})

data = topleveldict()

The topleveldict() function is only needed if you plan to create the structure in multiple places in your codebase. If there is just one such object or just one place you create these, then just inline the code from that function:

nested_dict = lambda *a, **kw: defaultdict(nested_dict, *a, **kw)
data = nested_dict(number=1)  # or nested_dict({'number': 1})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM