In Python wird die Datenstruktur dict oft verwendet, um verschachtelte Informationen zu speichern. Die Notwendigkeit, solche Strukturen zu klonen, begegnen Entwickler häufig bei der Arbeit mit Vorlagen, Konfigurationen oder beim Austausch von Daten zwischen Teilen der Anwendung.
Das Standardkopieren von dict mit Zuweisung (=) erstellt nur einen Verweis auf das ursprüngliche Objekt. Eine flache Kopie (shallow copy) kopiert nur das dict selbst, jedoch nicht die darin enthaltenen Objekte. Eine tiefe Kopie (deep copy) kopiert rekursiv alle Objekte innerhalb dessen, was Veränderungen in einer Kopie daran hindert, Auswirkungen auf die andere zu haben.
Für flaches Kopieren kann dict.copy() oder der Konstruktor dict() verwendet werden, für tiefe Kopien – das Modul copy und die Funktion deepcopy():
import copy d = {"a": 1, "b": {"c": 2}} shallow_d = d.copy() deep_d = copy.deepcopy(d) # Jetzt beeinflusst die Änderung von shallow_d['b']['c'] d['b']['c'] # Die Änderung von deep_d['b']['c'] hat keinen Einfluss auf das ursprüngliche Dictionary
Wichtige Merkmale:
Kann dict.copy() tiefer als die erste Ebene kopieren?
Nein, dict.copy() erstellt nur eine flache Kopie. Verschachtelte Dictionaries bleiben weiterhin Verweise auf dieselben Objekte wie im ursprünglichen dict.
Wenn die Struktur ein unveränderliches Objekt (wie ein Tupel) enthält, wird deepcopy es tief kopieren?
Deepcopy kopiert nur veränderbare untergeordnete Objekte. Unveränderliche Objekte bleiben unverändert – Tupel, Strings und Zahlen werden nicht rekursiv kopiert, sondern einfach in die Kopie übertragen.
Kann man zur tiefen Kopie die Serialisierung über json.loads(json.dumps(dict)) verwenden?
Ja, aber mit Vorbehalten. Diese Methode funktioniert nur für serialisierbare Typen und ist nicht geeignet, wenn im Dictionary nicht serialisierbare Objekte (z. B. Funktionen oder benutzerdefinierte Klassen) vorhanden sind:
import json orig = {"a": 10, "b": [1,2,3]} copy_like_deep = json.loads(json.dumps(orig)) # Funktioniert nicht für komplexe Objekte
** Negativer Fall
Ein Entwickler klont die Einstellungen über copy(), ändert dann einen untergeordneten Wert und geht davon aus, dass dies zwei unabhängige Strukturen sind.
Vorteile:
Einfach und schnell
Nachteile:
Änderungen an untergeordneten Objekten in einer Kopie wirken sich auf alle aus – Bugs, die schwer zu debuggen sind.
** Positiver Fall
Ein Entwickler verwendet immer copy.deepcopy() für verschachtelte Strukturen, auch wenn das ursprüngliche dict flach erscheint.
Vorteile:
Datenunabhängigkeit ist garantiert, Bugs sind auf ein Minimum reduziert
Nachteile:
Deepcopy ist langsamer und verbraucht mehr Speicher, manchmal überflüssig.