Hintergrund: Das Kopieren von Objekten (insbesondere Sammlungen – Listen, Wörterbücher) ist in Python entscheidend: Eine einfache Zuweisung zu einer Variablen erstellt eine neue Referenz, kein Duplikat. Die speziellen Methoden copy() und deepcopy() wurden geschaffen, um unerwünschte "Nebenwirkungen" bei der gemeinsamen Nutzung von Strukturen zu vermeiden.
Problem: Bei der Arbeit mit verschachtelten Sammlungen (Liste von Listen, Wörterbuch innerhalb eines Wörterbuchs) reproduziert ein einfaches copy() nur den Container, jedoch keine inneren Elemente. Dies kann zu schwer fassbaren Bugs führen: Eine Änderung an einem verschachtelten Element spiegelt sich in allen "Kopien" wider.
Lösung: copy.copy() erstellt eine flache Kopie (shallow copy) – einen neuen Container auf der obersten Ebene, aber die inneren Objekte bleiben die gleichen. copy.deepcopy() kopiert rekursiv alle inneren Objekte.
Beispielcode:
import copy lst = [[1, 2], [3, 4]] shallow = copy.copy(lst) deep = copy.deepcopy(lst) lst[0][0] = 10 print(shallow) # [[10, 2], [3, 4]] — das innere Objekt hat sich geändert! print(deep) # [[1, 2], [3, 4]] — deepcopy hat den ursprünglichen Zustand beibehalten
Wichtige Merkmale:
Reicht es manchmal aus, lst2 = lst[:] zum Kopieren einer Liste zu schreiben?
lst2 = lst[:] erstellt eine flache Kopie der Liste, aber die inneren Objekte (zum Beispiel Listen innerhalb der Liste) bleiben nach wie vor gleich. Für flache Listen ist das ausreichend; für verschachtelte Strukturen jedoch nicht.
Beispiel:
lst = [[1], [2]] lst2 = lst[:] lst[0][0] = 99 print(lst2) # [[99], [2]] — das innere Element hat sich in beiden "Kopien" geändert
Funktioniert die Methode .copy() bei allen Sammlungen gleich?
Nein. Zum Beispiel funktioniert dict.copy() als flaches Kopieren, list.copy() wurde erst mit Python 3.3 eingeführt, für set gibt es die Methode set.copy(). Bei Benutzerobjekten hängt die Unterstützung von .copy() von der implementierten Methode ab.
Kann man überall auf deepcopy verzichten? Ist das sicher und effizient?
Nein. deepcopy ist eine teure Operation: Sie kann Leistungsprobleme verursachen, insbesondere bei großen Strukturen und funktioniert nicht bei nicht kopierbaren/geschlossenen oder nicht standardmäßigen Objekten. Verwenden Sie deepcopy nur, wenn Sie wirklich eine vollständig unabhängige, rekursive Kopie benötigen.
In Tests wurde das Kopieren eines "Wörterbuchs von Wörterbüchern" über dict.copy() durchgeführt. Dadurch führten Anpassungen in der verschachtelten Struktur für einen Benutzer plötzlich zu Auswirkungen auf andere Tests (die Daten wurden global verändert).
Vorteile:
Nachteile:
Wir implementierten copy.deepcopy(), beschrieben in der Dokumentation die Ebenen der Verschachtelung und Besonderheiten der Struktur jedes Objekts und vermieden deepcopy für große Volumina, wo man "manuelle" Teilkopien machen konnte.
Vorteile:
Nachteile: