Search code examples
pythonpython-3.xcounter

Python: Weird result while indexing the dictionary from collections.Counter


Let's say I have a list of numbers

numbers = ['3', '3', '4', '4']

I want to count the number of occurrences of the elements in the list, so I use collections.Counter

from collections import Counter

result = Counter(numbers)

result
Counter({'3': 2, '4': 2})

Here's something that I find quite funny, if you try to index the Counter, it will always show 0 no matter what number of index you put into it.

result[0]
Out[22]: 0

result[1]
Out[23]: 0

result[100]
Out[24]: 0

result[10000000000]
Out[26]: 0

Any idea of this interesting results?


Solution

  • yes the counter collections inherits from dict and has a missing method implemented

    part of the code of the counter

    class Counter(dict):
        '''Dict subclass for counting hashable items.  Sometimes called a bag
        or multiset.  Elements are stored as dictionary keys and their counts
        are stored as dictionary values.
        '''
    
        def __missing__(self, key):
            'The count of elements not in the Counter is zero.'
            # Needed so that self[missing_item] does not raise KeyError
            return 0
    

    The dict type will always try to call missing. In case of the counter always returns 0

    See the dict documentation:

    d[key]
    Return the item of d with key key. Raises a KeyError if key is not in the map.

    If a subclass of dict defines a method __missing__() and key is not present, the d[key] operation calls that method with the key key as argument. The d[key] operation then returns or raises whatever is returned or raised by the __missing__(key) call. No other operations or methods invoke __missing__().

    When you do

    result[10000000000]
    >>> 0 
    

    you are not indexing the counter but accessing to the keys when the key is not present the count for that key is 0

    result["a"]
    >>> 0