嵌套的 defaultdict 引发 AttributeError

Nested defaultdict raises AttributeError

我正在使用嵌套的 defaultdict 来保持代码整洁并减少冗余代码。

我正在构建一个字典,例如:

{"Store1": {"Product1": 1}, "Store2": {"Product1": 2, "Product2": 1}}

我试图实现这个问题的答案,这会引发异常:

AttributeError: 'int' object has no attribute 'items'
from collections import defaultdict, Counter

d = defaultdict(lambda: defaultdict(lambda: Counter()))
d["Store1"]["Product1"] += 1
print(d)

有没有我可以的,例如:

d["Store1"]["Product1"] += 1

你需要写这样的东西

from collections import defaultdict, Counter

d = defaultdict(lambda: defaultdict(lambda: Counter()))
d["A"]["B"]["Store1"] += 1
print(d)

当您使用以下

d = defaultdict(lambda: defaultdict(lambda: Counter()))
d["Store1"]["Product1"] += 1

然后,d["Store1"] 将创建一个“类型”defaultdict(lambda: Counter()) 的新元素,因此 d["Store1"]["Product1"] 将创建一个 Counter 类型的新元素。因此,当您执行 += 1 时,它会尝试通过 1 增加 Counter 对象。但是,这没有定义,因为类型不兼容:

>>> 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'

如您所见,它假定右侧遵循 Mapping 协议并尝试添加 r.h.s。算作它自己。 IE。类似于:

>>> c = Counter(a=1)
>>> c += Counter(a=2, b=3)
>>> c
Counter({'a': 3, 'b': 3})

另一方面,当您使用 defaultdict(lambda: defaultdict(int)) 时,d["Store1"]["Product1"] 会创建一个新的 int 对象,该对象可以递增 += 1 并写回字典.