Python Nested Dictionaries

In the last lesson, we learned about Python Dictionary Methods. Now let’s organize more detailed data using dictionaries inside dictionaries.

Let’s Talk About Dictionaries Inside Dictionaries

We know what a dictionary is. It stores key-value pairs.

person = {
"name": "Alex",
"age": 25
}

But what if we want to store more complex information? Like a person who has a name, age, and also an address. And the address has a street, city, and zip code.

We could flatten it all into one dictionary.

person = {
"name": "Alex",
"age": 25,
"street": "123 Main St",
"city": "London",
"zip": "SW1A 1AA"
}

That works. But it gets messy. The address details are mixed in with the person details.

A better way is to use a nested dictionary. That is a dictionary inside another dictionary.

person = {
"name": "Alex",
"age": 25,
"address": {
"street": "123 Main St",
"city": "London",
"zip": "SW1A 1AA"
}
}

Now the address is its own dictionary. It is stored under the key "address". That keeps things organized.

How to Access Nested Values in Python

To access a value in a nested dictionary, we use multiple keys.

print(person["address"]["city"])

Output

London

First, person["address"] gives us the inner dictionary. Then ["city"] gives us the value.

We can go as deep as we want. If we had an inner dictionary inside another inner dictionary, we would just add more keys.

data = {
"user": {
"profile": {
"name": "Alex"
}
}
}
print(data["user"]["profile"]["name"])

Output

Alex

Adding and Changing Nested Values in Python

We can add new keys to a nested dictionary the same way.

person["address"]["country"] = "UK"
print(person["address"])

Output

{'street': '123 Main St', 'city': 'London', 'zip': 'SW1A 1AA', 'country': 'UK'}

We can also change existing values.

person["address"]["city"] = "Manchester"
print(person["address"]["city"])

Output

Manchester

Looping Through a Nested Dictionary in Python

We can loop through the outer dictionary. And for each inner dictionary, we can loop again.

person = {
"name": "Alex",
"age": 25,
"address": {
"street": "123 Main St",
"city": "London",
"zip": "SW1A 1AA"
}
}
for key, value in person.items():
if isinstance(value, dict):
print(f"{key}:")
for inner_key, inner_value in value.items():
print(f" {inner_key}: {inner_value}")
else:
print(f"{key}: {value}")

Output

name: Alex
age: 25
address:
street: 123 Main St
city: London
zip: SW1A 1AA

The isinstance(value, dict) checks if the value is a dictionary. If it is, we loop through it. Otherwise, we just print the value.

Python Nested Dictionaries: A Real-Life Example

Let’s store information about multiple people. Each person has their own dictionary.

people = {
"alex": {
"name": "Alex",
"age": 25,
"city": "London"
},
"sam": {
"name": "Sam",
"age": 30,
"city": "Manchester"
},
"john": {
"name": "John",
"age": 22,
"city": "Birmingham"
}
}
for username, info in people.items():
print(f"Username: {username}")
print(f" Name: {info['name']}")
print(f" Age: {info['age']}")
print(f" City: {info['city']}")
print()

Output

Username: alex
Name: Alex
Age: 25
City: London
Username: sam
Name: Sam
Age: 30
City: Manchester
Username: john
Name: John
Age: 22
City: Birmingham

That is a very common way to store records. Like a database.

Another Example β€” A Game Inventory

inventory = {
"weapons": {
"sword": 1,
"bow": 2,
"arrow": 50
},
"potions": {
"health": 5,
"mana": 3
},
"gold": 100
}
print(inventory["weapons"]["sword"])
print(inventory["potions"]["health"])
print(inventory["gold"])

Output

1
5
100

That keeps different categories of items separate.

Common Mistakes with Python Nested Dictionaries

Mistake 1: Forgetting a Level of Keys

person = {
"name": "Alex",
"address": {"city": "London"}
}
print(person["city"]) # Error!

So what do we do? We use the full path.

print(person["address"]["city"])

Mistake 2: Using the Wrong Key

print(person["address"]["country"]) # Error if country doesn't exist

So what do we do? We check if the key exists first, or use get().

print(person["address"].get("country", "Unknown"))

Mistake 3: Trying to Modify a Nested Value Directly Without the Inner Key

person["address"] = "London" # This replaces the whole address dictionary with a string

Let’s be careful. We are replacing the entire inner dictionary. If we only want to change the city, we use the full path.

person["address"]["city"] = "London"

Mistake 4: Thinking Nested Dictionaries Are Copied When We Copy the Outer Dictionary

import copy
original = {"a": {"b": 1}}
shallow = original.copy()
shallow["a"]["b"] = 2
print(original)

Output

{'a': {'b': 2}}

Because the inner dictionary is shared. We use copy.deepcopy() if we need a truly independent copy.

Next, we will learn about Python Dictionary Comprehensions and build dictionaries with concise expressions.