Counter & defaultdict
Counter and defaultdict are specialized dictionaries from the collections module: Counter tallies how often each item appears in one line, while defaultdict auto-creates a starting value for new keys so grouping and counting need no boilerplate checks.
Learn Counter & defaultdict in our free Python course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Counting and grouping are two of the most common tasks in all of programming. These two tools turn a fiddly ten-line loop into a clean one-liner.
Hand Counter any iterable — a list, a string, anything you can loop over — and it returns a dictionary of counts. The most_common() method then hands back the top items already sorted:
Counters support + and - to combine tallies element by element — perfect for merging counts from two days, or finding what changed. You can also update() to add more items in place:
Note that Counter.update() adds to existing counts rather than replacing values — the opposite of a normal dictionary's update() . That's exactly what you want when tallying.
A defaultdict takes a factory — a callable like list , int , or set — that produces the starting value for any key you touch for the first time. That means you can append or += without ever checking whether the key exists:
Replace each ___ so the code counts each word length using a defaultdict(int) .
❌ Passing the factory result instead of the factory
Group words that are anagrams of each other. The sorted letters of a word make a perfect grouping key.
Lesson complete — counting and grouping are now trivial!
You can tally any iterable with Counter , rank results with most_common() , combine tallies with Counter arithmetic, and group or count effortlessly with defaultdict(list) and defaultdict(int) — no more boilerplate "is this key here yet?" checks.
🚀 Up next: deque & Queues — a list-like container with O(1) operations on both ends.
Practice quiz
What does collections.Counter do when you pass it an iterable?
- Sorts it
- Counts how many times each element appears
- Removes duplicates
- Reverses it
Answer: Counts how many times each element appears. Counter tallies an iterable, returning a dict-like mapping of {element: count}.
What does Counter('mississippi') produce for the letter 'i'?
- A count of 1
- A count of 2
- A count of 4
- A KeyError
Answer: A count of 4. There are four 'i' characters in 'mississippi', so Counter records 'i': 4.
What does counter.most_common(2) return?
- The two rarest items
- The top 2 items as (item, count) tuples, sorted by count
- A count of 2
- The first two keys inserted
Answer: The top 2 items as (item, count) tuples, sorted by count. most_common(n) returns the n highest-count items as (item, count) tuples, already sorted from most to least common.
Accessing a missing key in a Counter, like tally['purple'], returns what?
- A KeyError
- None
- 0
- An empty string
Answer: 0. A Counter returns 0 for keys it has never seen, rather than raising KeyError.
How does Counter.update() behave differently from a plain dict's update()?
- It overwrites values
- It ADDS to existing counts instead of replacing them
- It deletes keys
- It does nothing for Counters
Answer: It ADDS to existing counts instead of replacing them. Counter.update() adds to existing counts (so update on a=5 with a=1 gives 6), the opposite of a normal dict's overwriting update().
What does the factory in defaultdict(int) produce for a brand-new key?
- None
- An empty list
- 0
- An empty string
Answer: 0. defaultdict(int) calls int() for new keys, producing 0 — so you can immediately do counts[key] += 1.
With defaultdict(list), why can you call d[key].append(x) on a new key?
- append creates the key
The list factory gives any new key a fresh [] on first access, so you can append without checking whether the key exists.
What is the catch with merely READING a missing key in a defaultdict?
- It raises KeyError
- It triggers the factory and inserts that key
- It returns None without inserting
- It deletes the dict
Answer: It triggers the factory and inserts that key. Reading d[missing] runs the factory and adds the key — handy for appending, but a typo while reading silently creates an entry. Use 'in' or .get() to check safely.
Which is the correct way to build a defaultdict of lists?
- defaultdict(list())
Pass the factory itself — the callable list, not list() or []. defaultdict(list()) raises TypeError because list() is not callable.
Given the Counters monday=Counter(apple=4) and tuesday=Counter(apple=1), what is (monday + tuesday)['apple']?
- 3
- 4
- 5
- 1
Answer: 5. Adding two Counters combines counts per key, so apple becomes 4 + 1 = 5.