defaultdict of defaultdict?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
A defaultdict of defaultdict creates a nested dictionary where accessing missing keys at any level automatically creates the intermediate structure instead of raising KeyError. The standard approach is defaultdict(lambda: defaultdict(list)) for a two-level nesting, but for arbitrary depth you can define a recursive factory. This pattern is useful for building tree-like structures, accumulating grouped data, and parsing hierarchical configurations without manual key-existence checks.
Basic defaultdict Review
Two-Level Nesting
The outer defaultdict uses a lambda because defaultdict(list) is not callable as a type — you need a zero-argument function that returns a new defaultdict(list).
Why Not defaultdict(defaultdict(list))?
Arbitrary Depth with Recursive Factory
Converting to Regular Dict
defaultdict creates empty entries on access, which can be surprising. Convert to a regular dict when you are done building the structure.
Practical Examples
Grouping Data by Multiple Keys
Building an Adjacency List
Common Pitfalls
- Passing an instance instead of a callable:
defaultdict(defaultdict(list))raisesTypeErrorbecausedefaultdict(list)is an instance, not a function. Usedefaultdict(lambda: defaultdict(list))— the lambda is the callable factory. - Accidental key creation on read access:
if data["missing_key"]creates the key with a default value as a side effect. Useif "missing_key" in datato check existence without creating the entry. This is especially problematic in nested defaultdicts where entire subtrees get created accidentally. - Lambda pickling issues: Lambdas are not picklable, so
defaultdict(lambda: defaultdict(list))cannot be serialized withpickleor used withmultiprocessing. Use a named function orfunctools.partialinstead:defaultdict(partial(defaultdict, list)). - Forgetting to convert before serialization:
json.dumps(data)fails on defaultdict because JSON does not understanddefaultdict. Convert to regular dicts before serializing to JSON, YAML, or other formats. - Deep nesting making code hard to understand: More than 2-3 levels of nested defaultdict becomes unreadable. For complex hierarchical data, use dataclasses, named tuples, or a proper tree/config class instead of deeply nested defaultdicts.
Summary
- Use
defaultdict(lambda: defaultdict(list))for two-level nested auto-creating dicts - The factory argument must be a callable (function/class), not an instance
- Use a recursive
tree()function for arbitrary-depth nesting - Convert to regular
dictbefore serialization or when done building the structure - Use named functions instead of lambdas if you need pickling support
Related reading
- Delayed message consumption in Kafka
- Delete a dictionary item if the key exists
- Delete all keys from a NSUserDefaults dictionary iOS
- Delete all the queues from RabbitMQ?
- Define a lambda expression that raises an Exception
- Define css class in django Forms
- Delete an element from a dictionary
- Deleting all but a few nodes in TensorFlow graph

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.