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.