I am using a nested defaultdict to keep code clean and reduce the redundant code.
I am constructing a dictionary such as:
{"Store1": {"Product1": 1}, "Store2": {"Product1": 2, "Product2": 1}}
I tried to implement the answer to this question Nested dictionary with defaults, which would raise the exception:
AttributeError: 'int' object has no attribute 'items'
from collections import defaultdict, Counter
d = defaultdict(lambda: defaultdict(lambda: Counter()))
d["Store1"]["Product1"] = 1
print(d)
is there anyway I can for example:
d["Store1"]["Product1"] = 1
CodePudding user response:
When you use the following
d = defaultdict(lambda: defaultdict(lambda: Counter()))
d["Store1"]["Product1"] = 1
then, d["Store1"]
will create a new element of "type" defaultdict(lambda: Counter())
and thus d["Store1"]["Product1"]
will create a new element of type Counter
. Hence when you do = 1
, it attempts to augment the Counter
object by 1
. This, however, is not defined, as the types are not compatible:
>>> c = Counter()
>>> c = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/---/lib/python3.7/collections/__init__.py", line 832, in __iadd__
for elem, count in other.items():
AttributeError: 'int' object has no attribute 'items'
As you can observe, it assumes that the right hand side follows the Mapping
protocol and it attempts to add the r.h.s. counts to its own. I.e. something like:
>>> c = Counter(a=1)
>>> c = Counter(a=2, b=3)
>>> c
Counter({'a': 3, 'b': 3})
When you use defaultdict(lambda: defaultdict(int))
on the other hand, then d["Store1"]["Product1"]
creates a new int
object, which can be incremented by = 1
and written back to the dict.
CodePudding user response:
You need to write something like that
from collections import defaultdict, Counter
d = defaultdict(lambda: defaultdict(lambda: Counter()))
d["A"]["B"]["Store1"] = 1
print(d)
CodePudding user response:
I think you have one too many defaultdict
s defined. The following works fine:
d = defaultdict(lambda: Counter())
d["Store1"]["Product1"] = 1
print(d)
Output:
{'Store1': {'Product1': 1}}