打印收集错误.计数器实例



计数器对象是dict的子类,所以它们有setdefault方法。

>>> from collections import Counter
>>> c = Counter(houses=5)
>>> print(c.setdefault.__doc__)
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

如果我这样做:

>>> c.setdefault('castles')
>>> c.keys()
dict_keys(['castles', 'houses'])
>>> type(c)
<class 'collections.Counter'>

一切似乎都很好。但是:

>>> c
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    c
  File "C:Python32libcollections.py", line 586, in __repr__
    items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
  File "C:Python32libcollections.py", line 477, in most_common
    return sorted(self.items(), key=_itemgetter(1), reverse=True)
TypeError: unorderable types: NoneType() < int()
>>> 

这是一个bug吗?不应该给c.setdefault('castles')一个值/键错误,而不是默默地接受一个没有值的键?或者考虑到None值的报告方法?

是的,看起来像个bug。问题是,没有值参数的setdefault假设值是None,而在Counter的情况下,它应该真正插入1或0,或者通过引发一些异常而失败。

顺便说一句,在Python 2.7中,您的代码片段可以工作。,尽管它仍然插入了None值,违反了Counter的不变量。

请注意,这不是我在collections.Counter中遇到的第一个错误/设计缺陷。

c.setdefault('castles')行直接赋值给c['castles'] = None。这可能不是你想要的。

如果你想让城堡__repr__中显示,使用c['castles'] = 0代替。

对于计数器可以是任何你想计数的值需要是一个数字。如您所见,__repr__中的排序步骤期望值都是数字,如果其中一个值被设置为None,它将不起作用。

setdefault似乎可以用来给计数器默认值或分配一个工厂函数,但这不是setdefault所做的。您根本不需要执行该步骤,因为Counter对象会自动为您返回默认值零。不需要额外的工作。

这是如何工作的,简单而容易:

>>> from collections import Counter
>>> c = Counter(houses=5)
>>> c
Counter({'houses': 5})
>>> c['castles']           # counters automatically return zero for missing items, no work required
0
>>> c                      # but missing items won't show in the __repr__
Counter({'houses': 5})
>>> c['castles'] = 0       # unless you specifically add an entry for them
>>> c
Counter({'houses': 5, 'castles': 0})

最新更新