Counter objects are subclasses of dict so they have the method 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
If I do:
>>> c.setdefault('castles')
>>> c.keys()
dict_keys(['castles', 'houses'])
>>> type(c)
<class 'collections.Counter'>
everything seems pretty nice. But:
>>> 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()
>>>
Is this a bug?. Should not give c.setdefault('castles') a value/key error instead of silently accept a key without value ? Or maybe a repr method taking into account None values?
Yes, looks like a bug. The problem is that
setdefaultwithout a value argument assumes the value isNone, while in the case of aCounterit should really insert either one or zero, or fail by raising some exception.In Python 2.7, your snippet works, btw., although it still inserts a
Nonevalue, violatingCounter‘s invariants.Mind you, this isn’t the first bug/design flaw that I encounter with
collections.Counter.