Toewijzing van een variabele (bijvoorbeeld, a = b) in Python kopieert het object niet, maar maakt alleen een nieuwe naam (verwijzing) naar het bestaande object. Wijzigingen via de ene naam zijn ook zichtbaar via de andere, als het een mutabel object is.
Shallow copy (oppervlakkige kopie), bijvoorbeeld via copy.copy(obj) of een slice [:] voor een lijst, creëert een nieuw bovenliggend object, maar geneste objecten binnenin worden via verwijzing gekopieerd (d.w.z. beide structuren "kijken" naar dezelfde subcontainers). Als geneste objecten worden gewijzigd, zijn de wijzigingen zichtbaar in beide objecten.
Voorbeeld:
import copy lst1 = [[1,2], [3,4]] lst2 = copy.copy(lst1) # of lst1[:] lst1[0][0] = 100 print(lst2) # [[100, 2], [3, 4]]
lst2 is een nieuwe lijst, maar het eerste element is dezelfde geneste lijst.
Vraag: Wat is het verschil tussen lst2 = lst1[:] en lst2 = copy.copy(lst1)?
Antwoord: In de praktijk zijn er geen verschillen voor gewone (éénlaag) lijsten — beide methoden maken een oppervlakkige kopie van de lijst. Echter, voor door de gebruiker gedefinieerde containerklassen kan er verschillend gedrag zijn (bijvoorbeeld, als een eigen __copy__ methode wordt geïmplementeerd). Evenzo is het veiliger om de gespecialiseerde copy module te gebruiken voor andere types (dict, set, etc.).
import copy lst1 = [1, 2, 3] lst2 = lst1[:] lst3 = copy.copy(lst1) print(lst2 == lst3) # True
Verhaal
In een project met configuratieverwerking dupliceerde de ontwikkelaar de standaardparameters via toewijzing params = default_params en rekende erop die "geïsoleerd" te kunnen wijzigen. Uiteindelijk leidden wijzigingen in een van de kopieën tot een cascade van wijzigingen in alle delen van de applicatie, omdat ze in feite met één object werkten.
Verhaal
Een onervaren programmeur gebruikte een oppervlakkige kopie van de lijst om de status van het spel op te slaan (game_states = states[:]). Bij een geneste structuur (lijsten van figuren op het bord) leidden wijzigingen binnen één status tot veranderingen in andere, waardoor de geschiedenis van terugspoelen en herhalingen kapot ging.
Verhaal
Bij het proberen om gegevens te klonen in een OOP-applicatie was de keuze tussen een slice en copy.copy(). Maar in de structuur was er een eigen klasse met een eigen copy-methode, die alleen werd meegenomen bij het gebruik van copy.copy(). De slice negeerde de logica van het kopiëren van het object, wat leidde tot onduidelijke bugs.