Oppervlakkige kopie (shallow copy) maakt een nieuw object op het bovenste niveau, maar geneste objecten (elementen van lijsten, geneste woordenboeken, enz.) delen het geheugen met het origineel. Diepe kopie (deep copy) kopieert alle niveaus van objecten recursief.
Te gebruiken via de module copy:
import copy original = [[1, 2], [3, 4]] shallow = copy.copy(original) deep = copy.deepcopy(original) shallow[0][0] = 99 # Verandert zowel original als shallow print(original) # [[99, 2], [3, 4]] # Nu met deep original = [[1, 2], [3, 4]] deep = copy.deepcopy(original) deep[0][0] = 99 print(original) # [[1, 2], [3, 4]]
copy.copy(obj): kopieert alleen de "wrapper"copy.deepcopy(obj): volledig recursieve kopieWat gebeurt er als je een tuple kopieert die veranderbare objecten bevat?
tuple is onveranderbaar, maar zijn elementen kunnen veranderbaar zijn (bijvoorbeeld, een lijst). Shallow copy en deep copy verschillen:
import copy t = ([1, 2], [3, 4]) shallow = copy.copy(t) deep = copy.deepcopy(t) shallow[0][0] = 99 print(t) # ([99, 2], [3, 4]) # Bij deep copy: t = ([1, 2], [3, 4]) deep = copy.deepcopy(t) deep[0][0] = 88 print(t) # ([1, 2], [3, 4])
Verhaal
In een documentverwerkingsapp werden gegevens opgeslagen in een lijst binnen een woordenboek. Bij het kopiëren van objecten met copy.copy veranderden geneste elementen per ongeluk bij het wijzigen van het nieuwe object. Dit leidde tot wijzigingen in de oorspronkelijke gegevens in andere delen van het systeem! Er vond data corruptie plaats. Het werd alleen opgelost door te vervangen door deepcopy.
Verhaal
In een machine learning-project, bij het opslaan van hyperparameters van modellen, werd een lijst van configuraties gekopieerd met standaard toewijzing en shallow copy, waarna verschillende experimenten hun parameters wederzijds wijzigden. De bron van de bug werd gevonden na een diagnose van het gedrag van het kopiëren van geneste lijsten via deepcopy.
Verhaal
In financiële software werd deep copy per ongeluk toegepast op een object dat een geopend bestand (handle) bevatte, wat resulteerde in TypeError: cannot pickle '_io.TextIOWrapper' object — omdat copy.deepcopy onder de motorkap pickle gebruikt. Dit werd opgelost door expliciete behandeling van dergelijke velden of door het aanroepen van shallow copy.