Python Nested Dictionaries
In this page:
Creating a Nested Dictionary
A nested dictionary is written just like a regular dictionary literal, except one or more of its values are themselves dictionary literals -- {"sam": {"age": 28, "city": "Austin"}} represents a single user's data nested one level inside an outer dictionary keyed by username.
Note: Format a nested dictionary literal across multiple lines with consistent indentation, making its hierarchical structure easy to read at a glance.
Warning: A deeply nested dictionary literal with many levels can become visually hard to read if not formatted with clear indentation.
Example: Creating a Nested Dictionary
data = {"sam": {"age": 28, "city": "Austin"}}
print(data)
Accessing Nested Values
Reaching a deeply nested value means chaining square-bracket lookups one level at a time -- data["users"]["sam"]["address"]["city"] walks through three levels of nesting to reach the final value, in the exact order the structure is nested.
Note: Read a chained nested lookup from left to right as "go into this key, then into that key, then that one" to keep track of which level you are navigating.
Warning: A missing key at ANY level in the chain (not just the final one) raises a KeyError at that specific level, which can be confusing if you assumed only the last key might be missing.
Example: Accessing Nested Values
data = {"users": {"sam": {"address": {"city": "Austin"}}}}
print(data["users"]["sam"]["address"]["city"])
Modifying Nested Dictionary Values
Updating a value inside a nested dictionary uses the same chained bracket syntax as reading it -- data["users"]["sam"]["age"] = 29 reaches into the nested structure and updates just that one specific value, leaving the rest of the structure untouched.
Note: Before modifying a deeply nested value, confirm every intermediate level already exists, or the assignment will raise a KeyError rather than automatically creating the missing levels.
Warning: Unlike some languages, Python does not automatically create missing intermediate dictionaries when you assign to a deeply nested path -- every level must already exist first.
Example: Modifying Nested Dictionary Values
data = {"users": {"sam": {"age": 28}}}
data["users"]["sam"]["age"] = 29
print(data)
Looping Over a Nested Dictionary
Looping over a nested dictionary typically means an outer loop over the top-level keys, with an inner loop (or direct access) handling each nested dictionary's own keys and values -- letting you process every piece of hierarchical data systematically.
Note: Use .items() at each level of the loop to get both the key and the nested value together, rather than looking up the value separately after getting just the key.
Warning: Forgetting that each iteration's value at the outer level IS itself a dictionary (not a plain value) is a common source of confusion when first looping over nested data.
Example: Looping Over a Nested Dictionary
users = {"sam": {"age": 28}, "alex": {"age": 30}}
for name, info in users.items():
print(name, info["age"])
The Shallow Copy Trap with Nested Dictionaries
Copying an outer dictionary with .copy() (or dict()) only copies the top level -- any nested dictionaries inside remain shared references between the original and the copy, meaning a change to a nested value through the copy still affects the original. copy.deepcopy() is needed for a genuinely independent copy.
Note: Use copy.deepcopy() specifically when you need a nested dictionary structure to be fully independent from the original, not just its top level.
Warning: Modifying a nested value through a shallow-copied dictionary silently also changes the original, since the nested dictionary itself was never actually duplicated.
Example: The Shallow Copy Trap with Nested Dictionaries
import copy
original = {"user": {"age": 28}}
shallow = original.copy()
shallow["user"]["age"] = 99
print(original["user"]["age"]) # also changed
deep = copy.deepcopy(original)
deep["user"]["age"] = 1
print(original["user"]["age"]) # unaffected
- Assuming a nested dictionary is copied independently when you copy the outer one with a shallow copy() -- the inner dictionaries remain shared references, not independent copies.
- Chaining several key lookups (data["users"]["sam"]["address"]) without checking each level actually exists first, risking a KeyError partway through the chain.
- Confusing a nested dictionary's structure with a list of dictionaries -- they solve different problems and are not interchangeable without restructuring.
- A nested dictionary is simply a dictionary whose values are themselves dictionaries, letting you represent hierarchical data naturally.
- Accessing a deeply nested value chains multiple square-bracket lookups: data["outer_key"]["inner_key"].
- Nested dictionaries can be built directly as a literal, or constructed incrementally by assigning dictionary values to keys.
Nested dictionaries are a natural consequence of core dict support, available in every Python version.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: