Skip to content

Collections Module

collections is a standard-library module of container types that solve common patterns the built-in list/dict/tuple don’t handle cleanly. The most-used one is defaultdict, a dict subclass that auto-creates a default value for missing keys instead of raising KeyError.

Grouping or counting with a plain dict means checking for the key every time:

words = ["cat", "dog", "cat", "bird", "dog", "cat"]
counts = {}
for w in words:
if w not in counts:
counts[w] = 0
counts[w] += 1
# or the slightly shorter counts[w] = counts.get(w, 0) + 1
from collections import defaultdict
words = ["cat", "dog", "cat", "bird", "dog", "cat"]
counts = defaultdict(int) # int() == 0, used for any missing key
for w in words:
counts[w] += 1 # no existence check needed
print(dict(counts)) # {'cat': 3, 'dog': 2, 'bird': 1}
groups = defaultdict(list)
for w in words:
groups[len(w)].append(w)
print(dict(groups)) # {3: ['cat', 'dog', 'cat', 'dog', 'cat'], 4: ['bird']}
  • No existence checks: accessing a missing key runs the factory function (int, list, set, or any zero-arg callable) instead of raising KeyError.
  • Purpose-built alternatives exist for the common cases: collections.Counter for counting (with .most_common() built in), collections.deque for a fast double-ended queue, collections.namedtuple/typing.NamedTuple for lightweight immutable records.
  • Reads closer to intent: counts[w] += 1 says β€œincrement the count for w,” without a get/setdefault dance in the way.
  • The factory (defaultdict(int)) is called with no arguments β€” it must be a zero-arg callable, not a value. defaultdict(0) fails; defaultdict(int) works because int() returns 0.
  • Merely checking if key in dd does not create the key, but any subscript access (dd[key]) does β€” including inside print(dd[key]) for a key that doesn’t exist yet, which is a common surprise.
  • Counter is arguably a better fit than defaultdict(int) purely for counting β€” same underlying behavior, but with .most_common(n), arithmetic between counters, and a friendlier repr.
from collections import Counter
counts = Counter(words)
print(counts.most_common(2)) # [('cat', 3), ('dog', 2)]
  1. What does defaultdict(list)[missing_key] do the first time missing_key is accessed?

    AnswerIt calls `list()` to create an empty list, stores it under `missing_key`, and returns it β€” no `KeyError`.
  2. Why does defaultdict(int) work for counting but defaultdict(0) does not?

    AnswerThe argument must be a zero-argument callable that produces the default value when invoked. `int` is callable (`int() == 0`); `0` is not callable at all.
  3. What’s a purpose-built alternative to defaultdict(int) specifically for counting?

    Answer`collections.Counter` β€” same auto-zero behavior, plus `.most_common()` and counter arithmetic.