计数器对象是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:\Python32\lib\collections.py", line 586, in __repr__
items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
File "C:\Python32\lib\collections.py", line 477, in most_common
return sorted(self.items(), key=_itemgetter(1), reverse=True)
TypeError: unorderable types: NoneType() < int()
>>>
这是一个错误吗?不应该给c.setdefault('castles')
一个值/键错误而不是默默地接受一个没有值的键?或者也许是一个考虑无值的repr方法?
答案 0 :(得分:2)
c.setdefault('castles')
行直接指定c['castles'] = None
。这可能不是你想要的。
如果您打算在 __ repr __ 中显示城堡,请改用c['castles'] = 0
。
要使计数器按设计行事,键可以是您想要计算的任何内容,值需要是一个数字。正如您所见, __ repr __ 中的排序步骤期望值都是数字,如果其中一个值设置为无,则它将不起作用。 / p>
似乎 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})
答案 1 :(得分:2)
是的,看起来像个bug。问题是没有值参数的setdefault
假定值为None
,而在Counter
的情况下,它应该实际插入一个或零,或者通过引发一些异常而失败。
在Python 2.7中,您的代码段可以正常工作,虽然它仍会插入None
值,但会违反Counter
的不变量。
请注意,这不是我与collections.Counter
遇到的第一个bug/design flaw。