Verschachtelte Dictionaries
Verschachtelte Dictionaries in Python erstellen, zugreifen, ändern, löschen und iterieren – mit Beispielen und Best Practices.
Ein verschachteltes Dictionary ist ein Dictionary, das andere Dictionaries als Werte enthält. Dadurch entsteht eine hierarchische (baumartige) Datenstruktur, die ideal für die Darstellung gruppierter Realdaten geeignet ist – etwa eine Sammlung von Benutzerprofilen, eine Konfigurationsdatei oder eine JSON-API-Antwort.
Dieses Kapitel behandelt:
- Erstellen verschachtelter Dictionaries
- Zugriff auf Werte in beliebiger Tiefe
- Ändern und Hinzufügen von Einträgen
- Löschen von Schlüsseln und Teil-Dictionaries
- Iterieren über verschachtelte Dictionaries
- Verwendung von
.get()zur Vermeidung vonKeyError - Arbeiten mit tief verschachtelten Daten und JSON
Verschachtelte Dictionaries erstellen
Definiere ein Dictionary, dessen Werte selbst Dictionaries sind:
people = {
"person1": {"name": "Alice", "age": 30},
"person2": {"name": "Bob", "age": 25},
}
print(people)
# {'person1': {'name': 'Alice', 'age': 30}, 'person2': {'name': 'Bob', 'age': 25}}Du kannst ein verschachteltes Dictionary auch schrittweise aufbauen:
people = {}
people["person1"] = {"name": "Alice", "age": 30}
people["person2"] = {"name": "Bob", "age": 25}
print(people["person1"]) # {'name': 'Alice', 'age': 30}Die Verschachtelungstiefe ist unbegrenzt – ein innerer Wert kann selbst wieder ein verschachteltes Dictionary sein.
Auf Werte in verschachtelten Dictionaries zugreifen
Verkette eckige Klammern, um in beliebige Ebenen vorzudringen:
Sicherer Zugriff mit .get()
Verkettete Klammer-Zugriffe lösen einen KeyError aus, wenn ein Schlüssel fehlt. Verwende .get(), um stattdessen einen Standardwert zurückzugeben:
people = {
"person1": {"name": "Alice", "age": 30},
}
# Safe: returns None if "person3" does not exist
print(people.get("person3", {}).get("name", "Unknown")) # Unknown
# Risky: raises KeyError
# print(people["person3"]["name"])Das Muster .get(outer_key, {}).get(inner_key, default) ist die idiomatische Methode, um optionale verschachtelte Daten ohne einen try/except-Block zu lesen.
Werte in verschachtelten Dictionaries ändern
Weise direkt über die Schlüsselkette zu:
Neue Teil-Dictionaries hinzufügen
Weise einem neuen äußeren Schlüssel ein neues Dictionary-Literal zu:
Mit setdefault() nur bei fehlendem Schlüssel hinzufügen
setdefault() fügt einen Schlüssel mit einem Standardwert nur dann ein, wenn er noch nicht existiert – nützlich beim Aufbau verschachtelter Dicts aus einem Datenstrom:
scores = {}
for student, subject, grade in [
("Alice", "math", 90),
("Alice", "english", 85),
("Bob", "math", 78),
]:
scores.setdefault(student, {})[subject] = grade
print(scores)
# {'Alice': {'math': 90, 'english': 85}, 'Bob': {'math': 78}}Schlüssel und Teil-Dictionaries löschen
Verwende del, um einen Schlüssel (und seinen Wert) auf beliebiger Ebene zu entfernen:
people = {
"person1": {"name": "Alice", "age": 30},
"person2": {"name": "Bob", "age": 25},
"person3": {"name": "Carol", "age": 40},
}
del people["person2"]["age"] # remove one key from an inner dict
del people["person3"] # remove an entire sub-dictionary
print(people)
# {'person1': {'name': 'Alice', 'age': 30}, 'person2': {'name': 'Bob'}}Verwende .pop(), wenn du den gelöschten Wert ebenfalls benötigst:
removed = people["person1"].pop("age", None)
print(removed) # 30
print(people["person1"]) # {'name': 'Alice'}Über verschachtelte Dictionaries iterieren
Über äußere Schlüssel und innere Einträge iterieren
people = {
"person1": {"name": "Alice", "age": 30},
"person2": {"name": "Bob", "age": 25},
}
for person_id, details in people.items():
print(f"{person_id}:")
for key, value in details.items():
print(f" {key}: {value}")Ausgabe:
person1:
name: Alice
age: 30
person2:
name: Bob
age: 25Ein verschachteltes Dict in eine Liste von Datensätzen umwandeln
Ein gängiges Muster bei der Datenvorbereitung für die Verarbeitung:
people = {
"person1": {"name": "Alice", "age": 30},
"person2": {"name": "Bob", "age": 25},
}
records = [
{"id": pid, **info}
for pid, info in people.items()
]
print(records)
# [{'id': 'person1', 'name': 'Alice', 'age': 30},
# {'id': 'person2', 'name': 'Bob', 'age': 25}]Tief verschachtelte Dictionaries
Python setzt keine Begrenzung für die Verschachtelungstiefe. Hier ist ein dreistufiges Beispiel, das die Abteilungsstruktur eines Unternehmens darstellt:
company = {
"engineering": {
"frontend": {
"lead": "Alice",
"headcount": 5,
},
"backend": {
"lead": "Bob",
"headcount": 8,
},
},
"marketing": {
"content": {
"lead": "Carol",
"headcount": 3,
},
},
}
# Access three levels deep
print(company["engineering"]["backend"]["lead"]) # Bob
# Iterate two levels and collect leads
leads = [
dept_data["lead"]
for dept_data in (
team
for teams in company.values()
for team in teams.values()
)
]
print(leads) # ['Alice', 'Bob', 'Carol']Beim Lesen tiefer Schlüssel, die möglicherweise fehlen, verkette .get()-Aufrufe:
lead = company.get("hr", {}).get("recruitment", {}).get("lead", "Not assigned")
print(lead) # Not assignedVerschachtelte Dictionaries und JSON
JSON-Objekte werden direkt auf Python-verschachtelte Dictionaries abgebildet. Das json-Modul konvertiert zwischen beiden:
import json
data = {
"users": {
"u1": {"name": "Alice", "active": True},
"u2": {"name": "Bob", "active": False},
}
}
# Serialize to JSON string
json_str = json.dumps(data, indent=2)
print(json_str)
# Deserialize back to a nested dict
restored = json.loads(json_str)
print(restored["users"]["u1"]["name"]) # AliceDies ist der typische Arbeitsablauf beim Konsumieren von REST-APIs oder beim Lesen von Konfigurationsdateien.
Häufige Fallstricke
Falle mit gemeinsamen Referenzen. Wenn du ein inneres Dict per Referenz kopierst und es dann änderst, werden sowohl das Original als auch die Kopie verändert:
original = {"a": {"x": 1}}
shallow = original.copy() # copies only the outer dict
shallow["a"]["x"] = 99
print(original["a"]["x"]) # 99 ← original is affected!Verwende copy.deepcopy(), wenn du eine vollständig unabhängige Kopie benötigst:
import copy
original = {"a": {"x": 1}}
deep = copy.deepcopy(original)
deep["a"]["x"] = 99
print(original["a"]["x"]) # 1 ← original is safeSiehe das Kapitel Dictionaries kopieren für einen vollständigen Vergleich von flacher und tiefer Kopie.
KeyError bei fehlenden Zwischenschlüsseln. Das Schreiben von d["a"]["b"] = 1 löst einen KeyError aus, wenn "a" noch nicht existiert. Verwende setdefault oder collections.defaultdict, um Zwischenebenen automatisch zu erstellen.
Kurzreferenz
| Aufgabe | Syntax |
|---|---|
| Auf inneren Wert zugreifen | d["outer"]["inner"] |
| Sicherer Zugriff | d.get("outer", {}).get("inner", default) |
| Inneren Schlüssel hinzufügen / aktualisieren | d["outer"]["inner"] = value |
| Neues Teil-Dict hinzufügen | d["new_key"] = {...} |
| Inneren Schlüssel löschen | del d["outer"]["inner"] |
| Teil-Dict löschen | del d["outer"] |
| Alle Einträge iterieren | for k, v in d.items(): for ik, iv in v.items(): |
| Tiefe Kopie | import copy; copy.deepcopy(d) |