Access nested dictionary items via a list of keys?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Accessing nested dictionary values from a list of keys is a common Python task when working with JSON-like data, configuration trees, or API payloads. The main idea is to walk the structure one step at a time until you either reach the final value or discover that the path is invalid.
The simple version is only a loop. The design question is how you want failures to behave: raise an error immediately, return a default, or support mixed dictionary-and-list paths.
The Basic Dictionary-Only Version
If every step is guaranteed to exist and every intermediate value is a dictionary, a short loop is enough.
This is fine when missing keys should be treated as real errors.
A Safe Version With a Default Value
In many applications, missing paths are expected. In that case, returning a default is often more useful than raising KeyError.
This version is safer when the input structure is external or partially optional.
Supporting Lists in the Path
Real payloads often mix dictionaries and lists. For example, a path may look like users, then index 1, then key name.
This is often the most practical general-purpose helper for nested JSON-like structures.
When Raising an Error Is Better
Returning a default is convenient, but sometimes it hides real schema bugs. If the data shape should be strict, letting the lookup fail can be the right design.
That is especially true when:
- the path is part of an internal contract
- missing data indicates a programming bug
- silent fallback would mask corrupted input
So the “safe” version is not always the best version. It depends on how trustworthy the data is supposed to be.
Use a Sentinel When None Is Ambiguous
If None is a legitimate stored value, returning None for “missing path” is ambiguous. In that case, use a sentinel object.
This keeps “missing” distinct from “present but value is None.”
Why Chained .get(...) Calls Are Limited
People sometimes try to solve the problem with chained dict.get calls.
This works for short, dictionary-only paths, but it becomes awkward when:
- the path length is dynamic
- lists appear in the structure
- you want consistent error or default handling
A loop-based helper is usually the cleaner abstraction.
Common Pitfalls
A common mistake is assuming every intermediate value is a dictionary. In mixed data, one step may be a list or None.
Another mistake is returning None for both missing paths and legitimate None values without distinguishing the cases.
Developers also sometimes overuse chained .get(...) calls when the path is dynamic and would be much clearer as a reusable helper.
Finally, decide deliberately whether a missing path should raise or quietly return a default. That is a design choice, not just a syntax choice.
Summary
- Walking a nested path is just repeated access through dictionaries or lists.
- Use a simple loop when missing keys should raise an error.
- Use a safe helper with a default when the input structure may be incomplete.
- Support integer path steps if the data can contain lists.
- Distinguish “missing” from “present but None” when that difference matters to the caller.

