Two Tools That Make Dicts Smarter
The idea
You know dicts. You know how to build them, read them, modify them.
The collections module has two tools that extend what dicts can do — and eliminate two patterns you've probably already written by hand.
Counter — count everything automatically
You have a list. You want to know how many times each value appears.
The manual way:
scores = [85, 74, 85, 91, 85, 74]
counts = {}
for score in scores:
if score in counts:
counts[score] += 1
else:
counts[score] = 1
print(counts)
The Counter way:
from collections import Counter
scores = [85, 74, 85, 91, 85, 74]
counts = Counter(scores)
print(counts)
Output → Counter({85: 3, 74: 2, 91: 1})
One line. Same result. Sorted by frequency automatically.
Counter works on any iterable — lists, strings, tuples:
letters = Counter("redhorndev")
print(letters)
# Counter({'r': 2, 'e': 2, 'd': 2, 'h': 1, 'o': 1, 'n': 1, 'v': 1})
Counter — useful methods
from collections import Counter
scores = [85, 74, 85, 91, 85, 74, 63]
counts = Counter(scores)
print(counts[85]) # 3 — how many times 85 appears
print(counts[99]) # 0 — missing key returns 0, not KeyError
print(counts.most_common(2)) # [(85, 3), (74, 2)] — top 2
most_common(n) returns the n most frequent elements as a list of tuples.
Missing keys return 0 — never a KeyError.
defaultdict — no more "key might not exist"
You want to group soldiers by squad. The manual way:
squads = {}
assignments = [("Alpha", "Raven"), ("Bravo", "Wolf"), ("Alpha", "Ghost")]
for squad, soldier in assignments:
if squad not in squads:
squads[squad] = []
squads[squad].append(soldier)
print(squads)
The defaultdict way:
from collections import defaultdict
squads = defaultdict(list)
assignments = [("Alpha", "Raven"), ("Bravo", "Wolf"), ("Alpha", "Ghost")]
for squad, soldier in assignments:
squads[squad].append(soldier)
print(dict(squads))
Output → {'Alpha': ['Raven', 'Ghost'], 'Bravo': ['Wolf']}
When you access a key that doesn't exist, defaultdict creates it automatically with the default value — here, an empty list.
You pass the type as the argument: defaultdict(list), defaultdict(int), defaultdict(set).
from collections import defaultdict
word_count = defaultdict(int)
words = ["bull", "raven", "bull", "ghost", "bull"]
for word in words:
word_count[word] += 1
print(dict(word_count))
# {'bull': 3, 'raven': 1, 'ghost': 1}
defaultdict(int) starts every new key at 0 — no check needed before incrementing.
Heads up!
Counteris a subclass of dict — all dict methods work on it- Missing keys in
Counterreturn0— notKeyError defaultdictcreates missing keys automatically — be aware if you checkinafter accessing- Wrap in
dict()when printingdefaultdictfor cleaner output
What you should understand now
Counter(iterable)counts occurrences of each elementCounter.most_common(n)returns the n most frequent elements- Missing keys in
Counterreturn0 defaultdict(type)creates missing keys with a default value automatically- Both eliminate boilerplate patterns you'd otherwise write by hand