Traverse Nested Dict Paths Depth-First in Python
Recursively walk a nested dictionary depth-first and yield each full path from root to leaf as lists.
Python code
32 linesdef depth_first_paths(node, path=None):
if path is None:
path = []
if not isinstance(node, dict):
yield path + [node]
return
for key, value in node.items():
new_path = path + [key]
if isinstance(value, dict):
yield from depth_first_paths(value, new_path)
else:
yield new_path + [value]
if __name__ == "__main__":
tree = {
"root": {
"left": {
"leaf1": 1,
"leaf2": 2
},
"right": {
"leaf3": 3,
"leaf4": 4
}
}
}
for path in depth_first_paths(tree):
print(path)
Output
['root', 'left', 'leaf1', 1]
['root', 'left', 'leaf2', 2]
['root', 'right', 'leaf3', 3]
['root', 'right', 'leaf4', 4]
How it works
The function checks if the current node is a dict: if not, it yields the accumulated path plus the scalar value and returns. For dicts, it loops over items, extends the path with the key, and either recurses (yield from) into sub-dicts or emits the complete path with the leaf value. Passing path=None and creating a fresh list avoids the classic mutable default-argument bug, so each recursive call gets its own list. Using a generator means the traversal is lazy and memory-friendly for huge trees.
Common mistakes
- Using a mutable default argument `path=[]` instead of `path=None`, causing paths to share state across calls
- Forgetting `yield from` for nested dicts, so nested paths never get emitted
- Treating lists inside the dict as leaves rather than continuing deeper
Variations
- Return list of paths (all at once) instead of yielding — call `list(depth_first_paths(tree))`
- Use `path.copy()` instead of `path + [key]` when accumulating paths manually
Real-world use cases
- Exporting every leaf value from a nested JSON config into a flat key list for validation or migration.
- Building a full map of API response fields to locate and update specific nested values.
- Flattening deeply nested YAML/JSON data for logging, dashboards, or data pipelines.
Sponsored
More from Dictionaries & sets
- Build a Case-Insensitive Dict with a Wrapper Class in Python medium
- Build a defaultdict histogram of categories in Python easy
- Build adjacency dict graph from edges in Python easy
- Build an OrderedDict insertion order demo in Python 3 easy
- Check Invertible Mapping for Duplicate Values in Python easy
- Compare Two Dictionaries in Python easy
Keep learning
Related tutorials and quizzes for this topic.