When you tally hashable things—log tokens, survey answers, letters in a string—you usually write d[k] = d.get(k, 0) + 1 over and over. Counter from collections is the friendlier version: think of it as a dict where each key is something you counted and each value is how many times it showed up. I keep this page close to what you actually type day to day; when you need every corner case, the official Counter documentation is the place to bookmark.
We will go from building counters from lists and strings, through reading and updating counts, word frequencies, most_common, elements, subtract, a little multiset-style arithmetic, cleanup, how this differs from a plain dict when you are counting, and a short “watch out for this” list at the end.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
What is Counter in Python?
Each key in a Counter is one distinct item you care about; the value is how many times you saw it. Here is the shape you will use most often—counting repeats in a Python list:
from collections import Counter
items = ["apple", "banana", "apple", "orange", "banana", "apple"]
counter = Counter(items)
print(counter)Run that on your side and you should see something like Counter({'apple': 3, 'banana': 2, 'orange': 1})—three apples, two bananas, one orange. That pretty-printed form is just how Counter chooses to show you its contents, not a separate “counter function” returning something exotic.
Import Counter from collections
I almost always import the class directly so my code stays short:
from collections import Counter
c = Counter()
print(type(c).__name__)You should see the name Counter. If your codebase already uses import collections everywhere, collections.Counter(...) is still fine—pick what reads best for you and your team.
Create a Counter from a list
You can hand Counter any iterable of hashable items. Lists of strings are the usual teaching example; tuples work the same way because Counter simply walks whatever sequence you give it.
from collections import Counter
items = ["b", "a", "s", "h", "b", "a", "a", "a"]
print(Counter(items))You should get per-letter counts. When the repr shows higher counts first, treat that as a display convenience from Counter, not something you should bake logic on top of—when you care about order, reach for most_common or sort explicitly yourself.
Create a Counter from a string
A string is iterable character by character, so Counter counts each letter (spaces too, if they appear in your string).
from collections import Counter
print(Counter("banana"))You should see how many a, b, and n characters appear in "banana".
Create a Counter from a dictionary
If you already have a mapping of keys to integer counts, you can seed a Counter from it—handy when you are merging tallies from somewhere else. Values should be integers (for ordinary counting they are usually zero or positive).
from collections import Counter
print(Counter({"b": 3, "a": 1, "z": 10}))You should see something like Counter({'z': 10, 'b': 3, 'a': 1}) (again, the repr likes to show larger counts first so you can skim it).
You can also write Counter(b=3, c=5) when your keys are valid identifiers—no intermediate dict required.
Access counts from a Counter
For you it feels like a dict: loop keys, index counts, or use .items() when you want (key, count) pairs together.
from collections import Counter
my_counter = Counter("bashir")
for item in my_counter:
print(item, my_counter[item])
for key, count in my_counter.items():
print(key, count)Each loop prints one line per character with its count. Here is the bit that saves you typing: a missing key does not explode with KeyError—you get 0, which is exactly what you want while you are counting.
from collections import Counter
my_counter = Counter("bashir")
print(my_counter["z"])That prints 0. If you want the broader story of how dicts behave outside counting, the Python dictionary tutorial is a good next read.
Add or update elements in a Counter
You bump counts the way you would with a mapping (counter[key] += n), and when you have a whole batch of new observations you call update(). Think of update as “add these counts on top of what I already have,” not “throw away what I had and replace the world.”
from collections import Counter
counter = Counter(["apple", "banana"])
counter["apple"] += 1
counter["orange"] += 1
print(counter)
counter.update(["apple", "orange", "orange"])
print(counter)After the first block you should see two apples, one banana, one orange; after update, apples tick up again and oranges gain two more hits. When you truly need to replace a tally wholesale, assign directly—for example counter["x"] = 5—and if that pattern feels unfamiliar, the add or update dictionary values guide walks the general dict story.
Count words using Counter
Split your text into words (here I use simple whitespace splitting via str.split; for more string ideas see split a string), then count the tokens. If you normalize or clean words first, list comprehensions pair nicely with this step. When you process logs or free-text survey answers, this is usually the pipeline you end up with.
from collections import Counter
text = "python is easy and python is popular"
words = text.split()
counter = Counter(words)
print(counter)You should see python and is counted twice and the other words once each.
Find most common items using most_common()
most_common(n) hands you up to n pairs of (element, count) sorted from the busiest item downward. The n is “how many leaderboard rows you want,” not “only show me items whose count is at least n.” If you leave n off or pass None, you get the full ranking order described in the docs.
from collections import Counter
counter = Counter("banana")
print(counter.most_common(2))You should see [('a', 3), ('n', 2)]—the two highest counts in "banana", not “only letters whose count is two or more.”
Expand items using elements()
The method is spelled elements()—note the s on the end. It yields each key repeated according to its positive count, which is handy when you want to feed a multiset-style pipeline. Zero or negative counts are skipped for you here.
from collections import Counter
my_counter = Counter({"x": 3, "y": 2, "z": -10})
for key in my_counter.elements():
print(key)You should see x three times and y twice, with no z lines, because non-positive counts do not expand.
Subtract counts using subtract()
When you need to back counts down, call subtract() with another iterable or mapping of deductions. It adjusts tallies in place instead of replacing your whole counter from scratch.
from collections import Counter
c = Counter(["a", "b", "a", "c"])
c.subtract(["a", "b", "b"])
print(c)Counts for a and b drop according to how often they appear in the argument. Keys may land on zero or dip negative; that affects elements() and some of the arithmetic helpers, so keep an eye on the sign when you are debugging.
Counter arithmetic operations
Once you are comfortable with update, subtract, and most_common, you might reach for +, -, &, and | when you want multiset-style math between two counters. The stdlib defines what each operator means for you—note that non-positive results may disappear from the printed result for some operations.
from collections import Counter
c1 = Counter({"x": 3, "y": 2})
c2 = Counter({"x": 1, "y": 3})
print(c1 + c2)
print(c1 - c2)
print(c1 & c2)
print(c1 | c2)You should see merged totals for +, clipped differences for -, per-key minimums for &, and per-key maximums for |, matching the official definitions.
Delete, clear, and remove zero or negative counts
You delete one key with del counter[key], wipe everything with counter.clear(), and when you want to drop zeros and negatives from a messy counter, unary + gives you a fresh counter with only positive counts—see the Counter arithmetic notes for why that works.
from collections import Counter
counter = Counter({"a": 2, "b": -1, "z": 0})
del counter["z"]
counter.clear()
print(counter)After clear() you should see an empty counter; del removed the z entry before the reset.
Counter vs dictionary for counting
With a plain dict you keep writing d[k] = d.get(k, 0) + 1 (or leaning on defaultdict(int)). Counter is the version where missing keys read as 0, update and subtract read like plain English, and helpers such as most_common and elements save you from reimplementing the same utilities. If you only need grouping without counts, other tools might fit better; when you care about frequencies, Counter is the idiom I reach for. When you wrap counting inside functions, passing a Counter in and out keeps your call sites small and obvious.
Common mistakes with Python Counter
Things I still catch in reviews:
- Importing
counterin lowercase—you wantCounterfromcollections. - Calling
Countera “function”—for you it is a class you instantiate. - Expecting
update()to replace values like some dict merges you have seen—it adds counts instead. - Reading
most_common(2)as “only show counts ≥ 2”—it means “give me the top two entries by frequency.” - Forgetting that missing keys return
0and then accidentally double-counting when you mix in other structures. - Expecting
elements()to emit keys with zero or negative counts—it skips non-positive counts on purpose. - Assuming
+or-always leaves zero or negative entries visible; the stdlib may strip non-positive entries depending on the operation.
Python Counter quick reference table
| What you want | What you usually write |
|---|---|
| Count an iterable | Counter(items) |
| Count characters | Counter(text) |
| Count words (simple split) | Counter(text.split()) |
| Bump or merge counts | c[k] += n or c.update(iterable_or_mapping) |
| Lower counts | c.subtract(iterable_or_mapping) |
| Top n frequencies | c.most_common(n) |
| Expand like a multiset | list(c.elements()) |
| Strip zeros / negatives | c = +c (see docs) |
| Sum of counts (3.10+) | c.total() |
| Clear everything | c.clear() |
Summary
You can lean on Counter as a dict subclass built for counting hashable objects: build it from lists, strings, or other mappings, read missing keys as 0, grow counts with += or update(), shrink them with subtract(), inspect frequencies with most_common, and expand with elements(). Read most_common(n) as “show me the top n pairs,” not as a threshold on the counts themselves. When multiset math is what you need, the documented +, -, &, and | operators are there once the basics feel natural under your fingers.

