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.

Medium Python 3.8+ Aug 9, 2026 Dictionaries & sets 13 views 0 copies

Python code

32 lines
Python 3.8+
def 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

stdout
['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

  1. Return list of paths (all at once) instead of yielding — call `list(depth_first_paths(tree))`
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Dictionaries & sets

Related tutorials and quizzes for this topic.