Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Grouping Data with collections.defaultdict

Use defaultdict factories to group values and initialize missing keys while understanding when lookups do and do not create entries.

Levels: Intermediate ~16 min read

Intermediate

A normal dictionary waits for you to decide what should happen when a key is missing. Sometimes a missing key has a predictable starting value: a new group should begin with an empty list, a set of tags should begin empty, or a record should start with zeroed fields. collections.defaultdict lets the dictionary create that initial value for you when you access a missing key with square brackets.

Group items as they arrive

Use list as the default factory when every key should collect a sequence of values. The factory is called separately for each new key, so different groups receive different lists.

Interactive Runnable example
Edit

Ready to run.

Quick check

Why is defaultdict(list) useful when grouping records?

from collections import defaultdict
groups = defaultdict(list)
groups["east"].append("tea")
groups["west"].append("coffee")
print(groups["east"])

The general dictionary lessons cover ordinary lookup, insertion, and get(). This lesson focuses on an automatic creation rule for repeated updates, especially when a program groups data as it processes it.

The factory runs for square-bracket lookup

defaultdict stores a callable in default_factory. When a missing key is requested with d[key], Python calls that factory with no arguments, stores the returned object under the key, and returns it. If the factory is None, the missing lookup raises KeyError as an ordinary dictionary does.

Interactive Runnable example
Edit

Ready to run.

Quick check

What happens when items.get("unknown") is used for an absent key in a defaultdict(list)?

from collections import defaultdict
items = defaultdict(list)
print(items.get("unknown"))
print("unknown" in items)

That difference is important: items["unknown"] is an operation that may mutate the mapping, while items.get("unknown") merely performs an ordinary dictionary-style lookup. Do not use square brackets just to inspect whether a key might exist.

Choose the factory for the value you need

The factory can be any callable that takes no required arguments. list creates an empty list; set creates an empty set for collecting unique values. The set factory is useful when repeated values should be discarded within each group.

Interactive Runnable example
Edit

Ready to run.

Quick check

Which factory fits a dictionary that stores unique tags for each project?

from collections import defaultdict
tags = defaultdict(set)
tags["docs"].add("python")
tags["docs"].add("python")
print(tags["docs"])

Create a fresh structured value per key

A small factory function can initialize a more structured value. Return a new object each time; do not return one shared mutable object from outside the factory, or separate keys could unexpectedly modify the same data.

Interactive Runnable example
Edit

Ready to run.

Quick check

How is a default_factory used for a missing key?

from collections import defaultdict
def make_value():
    return []
items = defaultdict(make_value)
items["x"].append(1)
print(items)

If calling the factory raises an exception, that exception propagates. The factory must match your value shape and should return a fresh mutable value for each key when independent state is required.

Choose defaultdict deliberately

Use defaultdict when missing-key access naturally means creating a new value for later mutation. Use dict.get() when you only need to read with a fallback and do not want to insert anything. The existing Counter lesson owns frequency counting; prefer Counter when the problem is tallying hashable items. A normal dictionary with setdefault() can also initialize one entry, but defaultdict often reads more clearly inside a repeated grouping loop.

Interactive Runnable example
Edit

Ready to run.

Quick check

Which tool should normally be chosen to count occurrences of hashable items?

from collections import Counter
counts = Counter("level")
print(counts["e"])

Key takeaways

  • Use list for grouped sequences, set for distinct values, or a callable that creates the structured value you need.
  • A missing d[key] lookup calls default_factory and stores its result; get() and membership checks do not.
  • Use defaultdict for automatic initialization, Counter for tallying, and ordinary dictionaries when lookup and insertion should stay explicit.

Quick check recap

Before moving on, explain when a new key should automatically create a value, why get() does not run the factory, and why each key needs an independent mutable object. Then complete the exercise and take the quiz.

Was this page helpful?

Mark this learning resource complete to track your learning progress.