collections.Counter

Hand it an iterable and it counts; hand it a mapping and it takes the counts as given. Reading a missing element gives 0 instead of KeyError, and + - & | work on whole counters.

collections classPython 3.1+Live demo
Common call
Counter('mississippi')
Returns
Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
Replaces
the "if key in d: d[key] += 1 else: d[key] = 1" loop
Watch out
a str is counted letter by letter — split it for words
collections.Counter(iterableiterable — Elements to count, or a mapping of element → count (taken as-is, zero and negative counts included).type: iterable | mapping · default: None=None, /, **kwds)
→ Counter

Demo

Live evaluation
Count the characters of any text. The repr lists elements from most to least common.
Try:
Inputs
textstrany text
Code
from collections import Counter
Counter('mississippi')
Result
Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})

In the repr, equal counts keep first-seen order: for "mississippi", i and s both appear 4 times and i comes first because it is met first. Subtraction and intersection drop anything that ends at zero or below, which is why a - b for "same" is an empty Counter(). A missing key reads as 0 but "key in c" stays False and len(c) does not grow.

Parameters

NameTypeRequiredDescription
iterableiterable | mappingno (None)Elements to count, or a mapping of element → count (taken as-is, zero and negative counts included).
**kwdsintnoCounts given as keyword arguments: Counter(a=2, b=1).

Return value

Counter — A new counter: each distinct element maps to how many times it was seen.

Common patterns

Word frequencies
Split first — a Counter over a str counts characters.
from collections import Counter
freq = Counter(text.lower().split())
freq.most_common(5)
Count by a derived key
Feed a generator expression.
from collections import Counter
by_ext = Counter(name.rsplit(".", 1)[-1] for name in filenames)
Is one multiset inside another?
Rich comparisons (3.10+) treat missing elements as zero.
from collections import Counter
can_build = Counter(word) <= Counter(letters)
Merge counts from several sources
sum() with a Counter start value, or update() in a loop.
from collections import Counter
total = sum((Counter(batch) for batch in batches), Counter())

Examples

1. Count words
from collections import Counter Counter('to be or not to be'.split())
Returns
Counter({'to': 2, 'be': 2, 'or': 1, 'not': 1})
2. Counts from keyword arguments
from collections import Counter Counter(apples=3, pears=1)
Returns
Counter({'apples': 3, 'pears': 1})
3. A mapping is taken as-is
from collections import Counter Counter({'a': 0, 'b': -2})
Returns
Counter({'a': 0, 'b': -2})
4. Add two counters
from collections import Counter Counter('aab') + Counter('abc')
Returns
Counter({'a': 3, 'b': 2, 'c': 1})
5. Anagram check
from collections import Counter Counter('listen') == Counter('silent')
Returns
True
6. Unary + drops zero and negative counts
from collections import Counter +Counter({'a': 2, 'b': 0, 'c': -1})
Returns
Counter({'a': 2})
7. del never raises
from collections import Counter c = Counter('ab') del c['zzz'] c
Returns
Counter({'a': 1, 'b': 1})
8. fromkeys is deliberately disabled
from collections import Counter Counter.fromkeys('abc')
Returns
NotImplementedError: Counter.fromkeys() is undefined. Use Counter(iterable) instead.

Pitfalls

1. Counting a string when you meant words
A str is an iterable of characters.
Counter(text)
from collections import Counter
Counter('hi hi').most_common(1)
[('h', 2)]
Counter(text.split())
from collections import Counter
Counter('hi hi'.split()).most_common(1)
[('hi', 2)]
2. Expecting subtraction to go negative
The - operator keeps only positive counts. subtract() keeps zero and negative results.
a - b
from collections import Counter
Counter(a=1) - Counter(a=3)
Counter()
a.subtract(b)
from collections import Counter
c = Counter(a=1)
c.subtract(Counter(a=3))
c
Counter({'a': -2})
3. Adding a plain dict
Counter arithmetic needs Counter on both sides; update() accepts any mapping.
c + dict
from collections import Counter
Counter(a=1) + {'a': 1}
TypeError: unsupported operand type(s) for +: 'Counter' and 'dict'
c.update(dict)
from collections import Counter
c = Counter(a=1)
c.update({'a': 1})
c
Counter({'a': 2})

When to use

Use it
  • Counting occurrences of anything hashable
  • Top-N rankings with most_common()
  • Multiset maths: combining, differencing, subset tests
Reach for something else
  • Counting a single value in a list → list.count(x)
  • Weighted or fractional tallies with negative values you want kept through + and - → a plain dict

Notes

CPython impl
Lib/collections/__init__.py; counting an iterable uses the C helper _count_elements from Modules/_collectionsmodule.c
repr order
repr() lists items in most_common() order — highest count first, ties in insertion order
Missing keys
__missing__ returns 0 without inserting; del of a missing key is silently ignored
copy()
Returns a new Counter with the same counts (a shallow copy); fromkeys() raises NotImplementedError

FAQ

collections.Counter(my_list) returns a dict-like object mapping each item to its count; counter.most_common(n) gives the n most frequent. For a single item, my_list.count(item) is enough.