collections Module
Python's built-in list, dict, and tuple cover most everyday needs, but the standard library's collections module adds a handful of specialized container types that solve very common problems more cleanly than hand-rolled code. This page covers the four you'll reach for most: Counter, defaultdict, OrderedDict, and deque.
`Counter`: Counting Hashable Items
Counter is a dict subclass built specifically for tallying up occurrences. Give it any iterable and it counts how many times each item appears.
from collections import Counter sentence = "the quick brown fox jumps over the lazy dog the fox runs" words = sentence.split() counts = Counter(words) print(counts) print(counts["the"]) print(counts["zebra"]) # missing keys return 0, not KeyError print(counts.most_common(3))
Counter({'the': 3, 'fox': 2, 'quick': 1, 'brown': 1, 'jumps': 1, 'over': 1, 'lazy': 1, 'dog': 1, 'runs': 1})
3
0
[('the', 3), ('fox', 2), ('quick', 1)].most_common(n) returns the n most frequent items as (item, count) tuples, sorted from highest to lowest count — perfect for word-frequency analysis, finding the most common value in a dataset, or building simple leaderboards.
`defaultdict`: Skipping the "Key Doesn't Exist Yet" Boilerplate
A very common pattern is building a dictionary where each key maps to a list (or another container) of related items. With a plain dict, you have to check whether the key already exists before appending to it:
students = [
("Math", "Ada"),
("Science", "Grace"),
("Math", "Alan"),
("Science", "Linus"),
("Math", "Katherine"),
]
by_subject = {}
for subject, name in students:
if subject not in by_subject:
by_subject[subject] = []
by_subject[subject].append(name)
print(by_subject){'Math': ['Ada', 'Alan', 'Katherine'], 'Science': ['Grace', 'Linus']}defaultdict removes the if key not in dict check entirely. You give it a factory function (called with no arguments) that produces a default value whenever a missing key is accessed — list for an empty list, int for zero, set for an empty set, and so on.
from collections import defaultdict
by_subject = defaultdict(list)
for subject, name in students:
by_subject[subject].append(name)
print(by_subject)
print(dict(by_subject)) # convert back to a plain dict if neededdefaultdict(<class 'list'>, {'Math': ['Ada', 'Alan', 'Katherine'], 'Science': ['Grace', 'Linus']})
{'Math': ['Ada', 'Alan', 'Katherine'], 'Science': ['Grace', 'Linus']}`OrderedDict`: Order With Explicit Intent
OrderedDict is a dict subclass that remembers the order keys were inserted. Since Python 3.7, regular dict objects already preserve insertion order as a language guarantee, so OrderedDict is far less necessary than it used to be — but it still has two things going for it: the .move_to_end() method, and communicating explicit intent to readers of your code.
from collections import OrderedDict
cache = OrderedDict()
cache["a"] = 1
cache["b"] = 2
cache["c"] = 3
cache.move_to_end("a")
print(cache)
cache.move_to_end("b", last=False) # move to the front instead
print(cache)OrderedDict({'b': 2, 'c': 3, 'a': 1})
OrderedDict({'b': 2, 'c': 3, 'a': 1})`deque`: Fast Appends and Pops From Both Ends
A list is optimized for adding/removing items at the end — append() and pop() are O(1). But inserting or removing from the front of a list — insert(0, x) or pop(0) — is O(n), because every remaining element has to shift over by one position. deque ("double-ended queue") is a container built specifically to make operations at both ends O(1).
Operation |
|
|
|---|---|---|
Append to right end | O(1) — | O(1) — |
Remove from right end | O(1) — | O(1) — |
Append to left end | O(n) — | O(1) — |
Remove from left end | O(n) — | O(1) — |
from collections import deque
queue = deque(["b", "c"])
queue.appendleft("a")
queue.append("d")
print(queue)
first = queue.popleft()
last = queue.pop()
print(first, last)
print(queue)deque(['a', 'b', 'c', 'd']) a d deque(['b', 'c'])
This makes deque the natural choice for queues, sliding-window algorithms, and breadth-first search, where items are constantly added and removed from the front of the collection.
And Don't Forget `namedtuple`
The collections module also includes namedtuple, for creating lightweight, immutable objects with named fields instead of relying on plain index-based tuples. It's covered in more depth elsewhere in this Python course, but it's worth remembering that it lives right alongside Counter, defaultdict, OrderedDict, and deque in the same module.
Quick Reference
Counter(iterable)tallies occurrences;.most_common(n)returns the top n as (item, count) pairs.defaultdict(factory)auto-creates missing keys using the given factory function, removing manual key checks.OrderedDictremembers insertion order and adds.move_to_end(); less essential since dicts preserve order natively.dequegives O(1)appendleft()/popleft()in addition toappend()/pop(), unlike a plainlist.namedtuple(covered elsewhere) rounds out the module for immutable, field-named tuples.