Nested Dictionary in Python: Create, Access, Update, and Loop

Learn nested dictionaries in Python with examples to create, access, update, add, delete, loop through, flatten, and merge dictionary inside dictionary data.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

Nested Dictionary in Python: Create, Access, Update, and Loop

A nested dictionary is a mapping whose values are themselves mappings (or mixed structures). That pattern shows up in JSON-style configuration, student records keyed by id, and API payloads. This tutorial walks through creating nested dicts, reading and updating inner fields, deleting safely, iterating, mixing lists as values, merging and flattening, and a few mistakes people hit with shared references.

If you are new to dicts in general, start with the Python dictionary guide. For flat merge rules (|, **, update), see merge dictionaries in Python. When you collect inner values into a list or view and only need “does any pass?” or “do all pass?” style answers, the built-in any() / all() helpers fit that pattern—see Python any() and all() (remember any(d) walks keys on a plain dict).

Tested on: Python 3.13.3; kernel 6.14.0-37-generic.


What is a nested dictionary in Python?

A nested dictionary is a dictionary inside a dictionary: some values are other dict objects, so you address inner data with chained keys such as outer["student1"]["age"]. The outer keys name groups (users, departments, locales); inner keys hold fields for each group. Python preserves insertion order in dicts (3.7+ in CPython); nesting does not change that, it only adds another layer of keys to navigate.

python
nested = {
    "student1": {"name": "Ada", "age": 22},
    "student2": {"name": "Lin", "age": 21},
}
print(nested["student1"]["name"])
Output

That prints Ada because nested["student1"] is a dict and ["name"] selects the inner field.


Create a nested dictionary in Python

You usually start from a literal, build with dict(), or assemble keys and values from lists.

Create a dictionary inside a dictionary

Use literals with braces: each value that should be a sub-record is written as its own {...}.

python
students = {
    "s1": {"name": "Ada", "class": 12},
    "s2": {"name": "Lin", "class": 11},
}
print(students)
Output

You get one top-level dict whose values are two inner dicts.

Create nested dictionary using dict()

dict() accepts keyword arguments only when keys are valid identifiers. For arbitrary string keys, pair iterables with zip or pass a list of (key, value) tuples.

python
by_keyword = dict(
    s1={"name": "Ada", "age": 22},
    s2={"name": "Lin", "age": 21},
)
keys = ["s1", "s2", "s3"]
profiles = [{"name": "Ada", "age": 22}, {"name": "Lin", "age": 21}, {"name": "Kim", "age": 20}]
by_zip = dict(zip(keys, profiles))
print(by_keyword["s1"]["name"], by_zip["s3"]["age"])
Output

That line prints Ada and 20, showing both construction styles.

Create nested dictionary from two lists

When one list holds outer ids and another holds matching inner dicts, zip plus dict is the usual idiom (same pattern as by_zip above).

python
ids = ["a100", "a101"]
rows = [{"role": "admin"}, {"role": "guest"}]
table = dict(zip(ids, rows))
print(table["a101"]["role"])
Output

The program prints guest.


Access values from a nested dictionary

Access inner dictionary values

Index from the outside in: first the outer key, then the inner key.

python
cfg = {"app": {"debug": True, "port": 8080}}
print(cfg["app"])
print(cfg["app"]["port"])
Output

The first print shows the whole inner dict; the second shows 8080.

Avoid KeyError while accessing nested values

Using [key] raises KeyError if any level is missing. Prefer .get per level with a default, or catch KeyError when you expect rare misses.

python
payload = {"user": {"name": "Ada"}}

print(payload.get("user", {}).get("email", "unknown"))
try:
    _ = payload["org"]["id"]
except KeyError as e:
    print("missing:", e)
Output

The first line prints unknown because email is absent. The try block prints a message showing which lookup failed.


Add or update values in a nested dictionary

Add a new inner dictionary

Assign a new key to a fresh dict, or assign an inner dict in one step.

python
db = {"s1": {"name": "Ada"}}
db["s2"] = {"name": "Lin", "age": 21}
print(db)
Output

db now has two top-level student entries.

Update value inside an inner dictionary

Assign through the full path to change one field without replacing the whole inner dict.

python
db = {"s1": {"name": "Ada", "age": 22}}
print("before:", db)
db["s1"]["age"] = 23
db["s1"]["city"] = "Pune"
print("after:", db)
Output

Age becomes 23 and a new inner key city appears under s1.


Delete items from a nested dictionary

Delete an inner dictionary

Use del on the outer key or pop if you want the removed value back.

python
db = {"s1": {"name": "Ada"}, "s2": {"name": "Lin"}}
removed = db.pop("s2")
print("removed:", removed)
print("left:", db)
Output

s2 disappears from db and removed holds the inner dict.

Delete a value from an inner dictionary

Remove one field inside a nested dict with del inner[key] or inner.pop("field").

python
db = {"s1": {"name": "Ada", "temp": True}}
del db["s1"]["temp"]
print(db)
Output

Only name remains under s1.


Loop through nested dictionary in Python

For control flow basics, see the Python for loop tutorial.

Loop through outer dictionary

items() gives (outer_key, inner_dict) pairs when values are dicts.

python
db = {"s1": {"name": "Ada"}, "s2": {"name": "Lin"}}
for sid, record in db.items():
    print(sid, "->", record["name"])
Output

Each line prints one student id and their name.

Loop through inner dictionary values

Nest a second loop over each inner mapping’s items() when you need every field.

python
db = {"s1": {"name": "Ada", "age": 22}, "s2": {"name": "Lin", "age": 21}}
for sid, record in db.items():
    print("---", sid)
    for field, value in record.items():
        print(field, value)
Output

You get each student block followed by name / age lines.


Nested dictionary with list values

Values do not have to be dicts only: a common shape is an outer key whose value is a list of dicts (rows, events, tasks).

python
dept = {
    "name": "Platform",
    "members": [{"name": "Ada", "level": "L5"}, {"name": "Lin", "level": "L4"}],
}
print(dept["members"][0]["name"])
print(len(dept["members"]))
Output

That prints the first member’s name and the list length. To append another row, use dept["members"].append({...}).


Merge nested dictionaries in Python

Shallow merge vs deep merge

Operators and methods such as |, {**a, **b}, and dict.update merge only the top level. If both dicts share a key whose value is another dict, the inner dict from the right-hand side replaces the inner dict from the left entirely (no automatic merge of inner keys).

python
import copy

left = {"user": {"name": "Ada", "score": 10}}
right = {"user": {"score": 99, "bonus": True}}
print("shallow |:", left | right)

deep_left = copy.deepcopy(left)
deep_left["user"].update(right["user"])
print("manual inner update:", deep_left)
Output

The shallow | result replaces the whole inner user dict with right’s version, so a field like name that only existed on the left disappears unless right defines it again. The deepcopy branch copies the left tree, then update merges keys inside user, so name can stay alongside updated scores and new keys.

For more patterns and ChainMap, see the merge section at the start of this page.


Flatten a nested dictionary

Flattening turns paths like a -> b -> c into one key such as a.b.c (or tuples) for CSV export or logging. Here is a compact recursive helper:

python
def flatten_dict(nested, parent_key="", sep="."):
    out = {}
    for key, value in nested.items():
        path = f"{parent_key}{sep}{key}" if parent_key else key
        if isinstance(value, dict):
            out.update(flatten_dict(value, path, sep=sep))
        else:
            out[path] = value
    return out

data = {"app": {"db": {"host": "localhost", "port": 5432}}, "debug": False}
print(flatten_dict(data))
Output

The flattened dict contains string keys like app.db.host and scalar values at the leaves.


Common mistakes with nested dictionaries

  • Reusing the same inner dict literal for multiple outer keys: every outer slot points at one shared object, so mutating one path changes “all” rows. Build a new dict per slot (copy of a template, dict comprehension, or copy.deepcopy).
  • Assuming {**a, **b} recursively merges inner dicts; it does not—plan shallow vs deep behavior explicitly.
  • Chaining [k1][k2][k3] in production without validation; prefer .get, schema validation, or typed models for untrusted input.

Python nested dictionary quick reference table

Task Typical pattern
Read inner value d["outer"]["inner"]
Safe read d.get("outer", {}).get("inner", default)
Replace inner record d["outer"] = {"k": "v"}
Patch one inner field d["outer"]["field"] = value
Remove outer group d.pop("outer") or del d["outer"]
Remove inner field del d["outer"]["field"]
Iterate outer then inner nested for over .items()
Shallow merge top level a | b, {**a, **b}, a.update(b)
Deep copy tree copy.deepcopy(d)
Flatten to dotted keys recursive walk emitting parent.child keys

Summary

Nested dictionaries model grouped records: outer keys identify rows or namespaces, inner keys hold fields. Create them with literals, dict, or zip of parallel lists; read and update with chained indices or safer .get; delete with del or pop at the right level; iterate with nested for loops over items(). When values are lists of dicts, index the list then the row dict. Merging and copying are shallow unless you use deepcopy or explicit inner updates, so inner dicts are the usual place bugs appear. Flatten with a short recursion when you need flat columns for export or display.


References


Frequently Asked Questions

1. What is a nested dictionary in Python?

It is a dictionary whose values include other mapping objects (usually dicts), so you model trees or records inside records with repeated key layers like outer["user"]["profile"].

2. How do I safely read a nested key that might be missing?

Chain .get on each level, use try/except KeyError, or normalize once with collections.defaultdict so missing branches do not raise during reads.

3. Does copying a nested dictionary copy the inner dictionaries too?

A shallow copy duplicates the outer dict but reuses inner dict objects; use copy.deepcopy when you need independent copies of every nested level.

4. How do I merge two nested dictionaries in Python?

Standard |, update, and {**a, **b} only shallow-merge top-level keys; for recursive field-by-field merging you need a custom function or a library—see the merge section and the dedicated merge dictionaries guide linked from this page.

5. How can I flatten a nested dictionary to dot keys like "a.b.c"?

Walk the tree recursively: for each dict value, recurse with a prefix built from parent keys; for non-dict values, emit one flat key–value pair into a new dict.
Bashir Alam

Data Analyst and Machine Learning Engineer

Computer Science graduate from the University of Central Asia, currently employed as a full-time Machine Learning Engineer at uExel. His expertise lies in OCR, text extraction, data preprocessing, and …