ProgrammierungBackend-Entwickler

Was ist der Unterschied zwischen shallow und deep copy in einer dict-Struktur, und wie kopiert man korrekt verschachtelte Dictionaries in Python?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Hintergrund

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.

Problem

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.

Lösung

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:

  • Flache Kopie kopiert nur die erste "Schicht" des Objekts
  • Tiefe Kopie kopiert rekursiv alle Objekte innerhalb der Struktur
  • Arbeiten Sie mit verschachtelten Strukturen immer mit deepcopy, wenn völlige Unabhängigkeit der Kopie erforderlich ist

Tückische Fragen.

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

Häufige Fehler und Anti-Patterns

  • Verwendung einfacher Zuweisung anstelle von Kopieren
  • Anwendung flacher Kopie auf verschachtelte Strukturen, was zu unerwarteten Änderungen in allen "Kopien" führt

Beispiel aus dem Leben

** 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.