- Creating nested dictionaries — dictionary inside a dictionary
- Accessing nested values — using keys to access nested data
- Adding and updating — modifying nested dictionary items
- Deleting items — removing nested key-value pairs
- Iteration — looping through nested dictionaries
- Advanced operations — merging, flattening, and more
- Common mistakes — and how to avoid them
Introduction to Nested Dictionaries
A nested dictionary is a dictionary that contains another dictionary (or other iterable) as a value. This allows you to create complex, hierarchical data structures that represent real-world relationships.
Nested dictionaries are commonly used for:
- Storing user data — users with profiles, addresses, preferences
- Configuration settings — nested application settings
- JSON data — representing API responses
- Database records — relational data representation
- Tree structures — hierarchical organizational data
💡 Key concept: Nested dictionaries enable you to model complex, real-world data structures in a natural and intuitive way.
Creating Nested Dictionaries
Building Nested Structures
Nested dictionaries can be created by assigning a dictionary as a value to a key, or by using nested curly braces.
# Creating a nested dictionary
user = {
"name": "Alice",
"age": 25,
"address": {
"street": "123 Main St",
"city": "NYC",
"zip": "10001"
},
"contacts": {
"email": "alice@example.com",
"phone": "555-1234"
}
}
print(user)
# {'name': 'Alice', 'age': 25, 'address': {'street': '123 Main St', 'city': 'NYC', 'zip': '10001'}, 'contacts': {'email': 'alice@example.com', 'phone': '555-1234'}}
# Creating nested dictionary incrementally
user = {"name": "Alice", "age": 25}
user["address"] = {}
user["address"]["street"] = "123 Main St"
user["address"]["city"] = "NYC"
user["address"]["zip"] = "10001"
# Nested dictionary with lists
user = {
"name": "Alice",
"orders": [
{"id": 1, "product": "Laptop", "price": 999.99},
{"id": 2, "product": "Mouse", "price": 29.99}
]
}
print(user)
# Multiple levels of nesting
data = {
"level1": {
"level2": {
"level3": {
"value": "Deep nested value"
}
}
}
}
print(data["level1"]["level2"]["level3"]["value"]) # Deep nested value
Methods:
- Direct creation — nested curly braces
- Incremental creation — building step by step
- Mixed structures — dictionaries containing lists of dictionaries
- Deep nesting — multiple levels of nesting
Quick Check: What is a nested dictionary? (Answer: A dictionary that contains another dictionary as a value)
Accessing Nested Values
Reading Values from Nested Structures
Accessing nested values requires using multiple keys in sequence. You can also use get() for safe access.
# Accessing nested values
user = {
"name": "Alice",
"address": {
"street": "123 Main St",
"city": "NYC",
"zip": "10001"
},
"contacts": {
"email": "alice@example.com",
"phone": "555-1234"
}
}
# Direct access
print(user["address"]["city"]) # NYC
print(user["contacts"]["email"]) # alice@example.com
# Using get() for safe access
city = user.get("address", {}).get("city", "Unknown")
print(city) # NYC
country = user.get("address", {}).get("country", "USA")
print(country) # USA
# Accessing deeply nested values
user = {
"data": {
"profile": {
"details": {
"name": "Alice"
}
}
}
}
name = user.get("data", {}).get("profile", {}).get("details", {}).get("name", "Unknown")
print(name) # Alice
# Using try-except for safe access
try:
phone = user["contacts"]["phone"]
print(phone) # 555-1234
except KeyError:
print("Phone not found")
Methods:
- Direct indexing —
dict[key1][key2] - get() method — safe access with defaults
- try-except — handle missing keys gracefully
- Deep access — chaining
get()calls
Quick Check: What is the safe way to access nested values? (Answer: Using get() with default values)
Adding and Updating Nested Values
Modifying Nested Data
Adding and updating nested values requires accessing the nested structure and assigning new values.
# Updating existing nested values
user = {
"name": "Alice",
"address": {"city": "NYC", "zip": "10001"}
}
user["address"]["city"] = "LA"
print(user) # {'name': 'Alice', 'address': {'city': 'LA', 'zip': '10001'}}
# Adding new nested keys
user["address"]["street"] = "456 Oak Ave"
print(user) # {'name': 'Alice', 'address': {'city': 'LA', 'zip': '10001', 'street': '456 Oak Ave'}}
# Adding a new nested dictionary
user["contacts"] = {
"email": "alice@example.com",
"phone": "555-1234"
}
print(user)
# Adding deeply nested values safely
user = {"name": "Alice"}
user.setdefault("address", {})["city"] = "NYC"
print(user) # {'name': 'Alice', 'address': {'city': 'NYC'}}
# Using update() with nested dictionaries
user = {"name": "Alice", "address": {"city": "NYC"}}
user["address"].update({"zip": "10001", "street": "123 Main St"})
print(user) # {'name': 'Alice', 'address': {'city': 'NYC', 'zip': '10001', 'street': '123 Main St'}}
Methods:
- Direct assignment —
dict[key1][key2] = value - setdefault() — safely create nested keys
- update() — update multiple values at once
- Deep assignment — adding nested structures
Quick Check: How do you safely add a nested key that might not exist? (Answer: Using setdefault() or get() with assignment)
Deleting Nested Items
Removing Nested Key-Value Pairs
Deleting items from nested dictionaries requires using del or pop() on the nested structure.
# Deleting a nested value
user = {
"name": "Alice",
"address": {"city": "NYC", "zip": "10001", "street": "123 Main St"}
}
del user["address"]["street"]
print(user) # {'name': 'Alice', 'address': {'city': 'NYC', 'zip': '10001'}}
# Using pop() with nested keys
phone = user.get("contacts", {}).pop("phone", None)
print(phone) # None (not found)
# Deleting an entire nested dictionary
user = {
"name": "Alice",
"address": {"city": "NYC", "zip": "10001"},
"contacts": {"email": "alice@example.com"}
}
del user["contacts"]
print(user) # {'name': 'Alice', 'address': {'city': 'NYC', 'zip': '10001'}}
# Deleting nested values safely
if "address" in user and "city" in user["address"]:
del user["address"]["city"]
print(user)
Methods:
- del — removes the nested key-value pair
- pop() — removes and returns the value
- Check existence — verify keys exist before deletion
- popitem() — remove and return last item
Quick Check: How do you safely delete a nested value? (Answer: Check if the key exists first or use pop() with a default)
Iterating Over Nested Dictionaries
Looping Through Nested Structures
Iterating over nested dictionaries requires nested loops or recursive functions to access all levels.
# Iterating over nested dictionaries
users = {
"user1": {"name": "Alice", "age": 25},
"user2": {"name": "Bob", "age": 30},
"user3": {"name": "Charlie", "age": 35}
}
for user_id, data in users.items():
print(f"{user_id}: {data['name']} is {data['age']} years old")
# Nested iteration with loops
user = {
"name": "Alice",
"address": {"city": "NYC", "zip": "10001"}
}
for key, value in user.items():
if isinstance(value, dict):
for sub_key, sub_value in value.items():
print(f"{key}.{sub_key}: {sub_value}")
else:
print(f"{key}: {value}")
# Recursive iteration for deep nesting
def print_nested(data, indent=0):
for key, value in data.items():
if isinstance(value, dict):
print(" " * indent + f"{key}:")
print_nested(value, indent + 2)
else:
print(" " * indent + f"{key}: {value}")
user = {
"name": "Alice",
"profile": {
"address": {"city": "NYC", "zip": "10001"},
"contacts": {"email": "alice@example.com"}
}
}
print_nested(user)
# Using recursion to flatten a nested dictionary
def flatten_dict(data, parent_key=""):
items = []
for key, value in data.items():
new_key = f"{parent_key}.{key}" if parent_key else key
if isinstance(value, dict):
items.extend(flatten_dict(value, new_key).items())
else:
items.append((new_key, value))
return dict(items)
flattened = flatten_dict(user)
print(flattened)
Methods:
- Nested loops — iterate over each level
- Recursive iteration — handle any depth
- Flattening — convert nested to flat dictionary
- isinstance() — check for nested structures
Quick Check: How do you iterate over a deeply nested dictionary? (Answer: Use recursion or nested loops)
Advanced Operations
Merging, Flattening, and More
Advanced operations on nested dictionaries include merging, flattening, and deep searching.
# Merging nested dictionaries (deep merge)
def merge_dicts(dict1, dict2):
result = dict1.copy()
for key, value in dict2.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = merge_dicts(result[key], value)
else:
result[key] = value
return result
dict1 = {"a": 1, "b": {"c": 2, "d": 3}}
dict2 = {"b": {"d": 4, "e": 5}, "f": 6}
merged = merge_dicts(dict1, dict2)
print(merged) # {'a': 1, 'b': {'c': 2, 'd': 4, 'e': 5}, 'f': 6}
# Deep flattening (flatten all levels)
def deep_flatten(data, parent_key="", sep="."):
items = {}
for key, value in data.items():
new_key = f"{parent_key}{sep}{key}" if parent_key else key
if isinstance(value, dict):
items.update(deep_flatten(value, new_key, sep))
else:
items[new_key] = value
return items
data = {"a": {"b": {"c": 1, "d": 2}}, "e": 3}
flattened = deep_flatten(data)
print(flattened) # {'a.b.c': 1, 'a.b.d': 2, 'e': 3}
# Deep searching
def search_nested(data, target):
for key, value in data.items():
if key == target:
return value
if isinstance(value, dict):
result = search_nested(value, target)
if result is not None:
return result
return None
user = {"profile": {"details": {"name": "Alice", "age": 25}}}
result = search_nested(user, "age")
print(result) # 25
# Counting nested elements
def count_nested_items(data):
count = 0
for value in data.values():
if isinstance(value, dict):
count += count_nested_items(value)
else:
count += 1
return count
user = {"a": 1, "b": {"c": 2, "d": {"e": 3}}}
print(count_nested_items(user)) # 3
Operations:
- Deep merge — recursive dictionary merging
- Deep flatten — convert nested to flat structure
- Deep search — find values by key
- Deep count — count all leaf values
Common Mistakes
Watch Out For These!
Mistake 1: Accessing Non-Existent Nested Keys
# WRONG — raises KeyError
user = {"name": "Alice"}
# city = user["address"]["city"] # KeyError: 'address'
# CORRECT — use get() with defaults
city = user.get("address", {}).get("city", "Unknown")
Mistake 2: Accidentally Sharing Nested Dictionaries
# WRONG — nested dictionary is shared
users = {}
for id in [1, 2, 3]:
users[id] = {}
users[id]["name"] = f"User {id}"
print(users) # Works correctly in this case
# CORRECT — be careful with mutable defaults
def create_user(name, data=None):
if data is None:
data = {}
return {"name": name, "data": data}
Mistake 3: Not Handling Missing Keys in Deep Access
# WRONG — fails if any key is missing
user = {"profile": {"details": {"name": "Alice"}}}
# city = user["profile"]["address"]["city"] # KeyError
# CORRECT — use nested get()
city = user.get("profile", {}).get("address", {}).get("city", "Unknown")
Quick Check: What is the most common mistake with nested dictionaries? (Answer: Accessing non-existent nested keys)
Interactive Editor
Experiment with nested dictionaries directly in your browser. Modify the code and see the results in real time.
NESTED DICTIONARY PRACTICE
========================================
Original: {'name': 'Alice', 'age': 25, 'address': {'street': '123 Main St', 'city': 'NYC', 'zip': '10001'}, 'contacts': {'email': 'alice@example.com', 'phone': '555-1234'}}
1. ACCESSING NESTED VALUES
City: NYC
Email: alice@example.com
2. SAFE ACCESS WITH GET()
City: NYC
Country: USA
3. ADDING AND UPDATING
Updated: {'name': 'Alice', 'age': 25, 'address': {'street': '456 Oak Ave', 'city': 'NYC', 'zip': '10001'}, 'contacts': {'email': 'alice@example.com', 'phone': '555-5678'}}
4. ADDING NESTED STRUCTURES
After adding preferences: {'name': 'Alice', 'age': 25, 'address': {'street': '456 Oak Ave', 'city': 'NYC', 'zip': '10001'}, 'contacts': {'email': 'alice@example.com', 'phone': '555-5678'}, 'preferences': {'theme': 'dark', 'notifications': True}}
5. ITERATING
name: Alice
age: 25
address:
street: 456 Oak Ave
city: NYC
zip: 10001
contacts:
email: alice@example.com
phone: 555-5678
preferences:
theme: dark
notifications: True
Nested dictionary practice complete!
Certificate of Completion
You have completed the Python Nested Dictionary tutorial. You understand creating, accessing, updating, deleting, iterating, and advanced operations on nested dictionaries.
Quick Quiz — Test Your Knowledge
Let's see what you've learned about nested dictionaries:
Frequently Asked Questions
What is a nested dictionary?
How do I safely access nested values?
get() method with default values: value = dict.get('key', {}).get('nested_key', default). This prevents KeyError exceptions.
How do I flatten a nested dictionary?
{"a.b.c": value}.
How do I merge two nested dictionaries?
dict1.update(dict2) but this only merges the top level.
Can I have lists inside nested dictionaries?
How do I iterate over a nested dictionary?
flatten_dict() approach.
Where to Go From Here
After mastering nested dictionaries, consider exploring these related topics:
Dictionary Comprehension
Create dictionaries concisely using comprehension syntax.
Learn More →JSON Module
Learn more about working with JSON data in Python.
Learn More →Dictionary Assignments
Practice your dictionary skills with assignments.
Learn More →