打印collection.Counter实例时出错

时间:2011-11-05 18:35:24

标签: python python-3.x

计数器对象是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方法?

2 个答案:

答案 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