Pythoncollections Module

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.

Python
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.

Tip
Because `Counter` is a `dict` subclass, it also supports arithmetic between counters — `counter_a + counter_b` adds counts together, and `counter_a - counter_b` subtracts them.
`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:

Python
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.

Python
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 needed
defaultdict(<class 'list'>, {'Math': ['Ada', 'Alan', 'Katherine'], 'Science': ['Grace', 'Linus']})
{'Math': ['Ada', 'Alan', 'Katherine'], 'Science': ['Grace', 'Linus']}
Warning
Accessing a missing key on a `defaultdict` **creates** that key with the default value. This is exactly what you want when building up grouped data, but it means checking `if key in some_defaultdict` after an accidental lookup can behave surprisingly — the lookup itself may have just inserted the key.
`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.

Python
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})
Note
`.move_to_end()` is the main reason to reach for `OrderedDict` today — it's the building block behind simple least-recently-used (LRU) cache implementations. If you only need insertion order preserved (not reordering), a plain `dict` is enough on modern Python.
`deque`: Fast Appends and Pops From Both Ends

A list is optimized for adding/removing items at the endappend() 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

list

deque

Append to right end

O(1) — append()

O(1) — append()

Remove from right end

O(1) — pop()

O(1) — pop()

Append to left end

O(n) — insert(0, x)

O(1) — appendleft()

Remove from left end

O(n) — pop(0)

O(1) — popleft()

Python
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.

Tip
`deque` also accepts a `maxlen` argument, turning it into a fixed-size rolling buffer that automatically drops items from the opposite end once it's full — handy for things like "keep the last 10 log lines".
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.

  • OrderedDict remembers insertion order and adds .move_to_end(); less essential since dicts preserve order natively.

  • deque gives O(1) appendleft()/popleft() in addition to append()/pop(), unlike a plain list.

  • namedtuple (covered elsewhere) rounds out the module for immutable, field-named tuples.