【问题标题】:Nested defaultdict raises AttributeError嵌套的 defaultdict 引发 AttributeError
【发布时间】:2022-01-12 00:48:52
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • defaultdict(lambda: defaultdict(int)) 呢?
  • 这行得通! :)。你能解释一下它为什么起作用吗?如果您将其添加为答案,我也可以将您的评论标记为解决方案。谢谢

标签: python dictionary defaultdict


【解决方案1】:

当您使用以下内容时

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

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

>>> 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 并写回字典。

【讨论】:

  • 感谢您的回答和解释! ;)
【解决方案2】:

我认为您定义的defaultdicts 太多了。以下工作正常:

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

输出:

{'Store1': {'Product1': 1}}

【讨论】:

    【解决方案3】:

    你需要写这样的东西

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

    【讨论】:

      猜你喜欢
      • 2013-10-11
      • 2021-12-01
      • 2021-11-28
      • 2020-08-02
      • 2022-10-06
      • 2016-04-07
      相关资源
      最近更新 更多