Below is a sample code:
from collections import defaultdict
normal_dict = {
"test": {
"test1": 1,
"test2": 2,
"test3": {
"test3_1": 1
}
}
}
default_dict = defaultdict(lambda: defaultdict(dict), normal_dict)
default_dict['test']['test4']['test4_1'] = 1 # Doesn't work
print(default_dict)
I get this error
Traceback (most recent call last):
File "<string>", line 17, in <module>
KeyError: 'test4'
It seems like the previously non-existent key 'test4'
is not being automatically added when I use the line default_dict['test']['test4']['test4_1']
, for some reason. Theoretically, defaultdict should create the key test4
with another defaultdict as its default value.
CodePudding user response:
The Problem
The problem is that:
default_dict['test']
is:
{'test1': 1, 'test2': 2, 'test3': {'test3_1': 1}}
in other words is a dictionary not a defaultdict
. Note that defaultdict
provides a value (through the factory method) for a missing key, which is not the case at creation time in:
default_dict = defaultdict(lambda: defaultdict(dict), normal_dict)
It won't copy the values and "transform" them to defaultdict.
One solution
One approach, that transform every nested dictionary into a defaultdict is the following:
def nested_dd():
# https://stackoverflow.com/a/19189356/4001592
return defaultdict(nested_dd)
def convert_to_default(d):
res = nested_dd()
for key, value in d.items():
if isinstance(value, dict):
res[key] = convert_to_default(value)
else:
res[key] = value
return res
result = convert_to_default(normal_dict)
result['test']['test4']['test4_1'] = 1
pprint.pprint(result) # need to import pprint
Output
defaultdict(<function nested_dd at 0x7fd27008bd90>,
{'test': defaultdict(<function nested_dd at 0x7fd27008bd90>,
{'test1': 1,
'test2': 2,
'test3': defaultdict(<function nested_dd at 0x7fd27008bd90>,
{'test3_1': 1}),
'test4': defaultdict(<function nested_dd at 0x7fd27008bd90>,
{'test4_1': 1})})})