Achtergrond: In Python is het kopiëren van objecten (vooral verzamelingen — lijsten, dictionaries) cruciaal: eenvoudige toewijzing van een variabele creëert een nieuwe referentie, geen kopie. Speciale methoden copy() en deepcopy() zijn ontwikkeld om ongewenste "bijwerkingen" bij het gezamenlijk gebruik van structuren te voorkomen.
Probleem: Bij het werken met geneste verzamelingen (lijst van lijsten, dictionary binnen een dictionary) reproduceert een eenvoudige copy() alleen de container zelf, maar niet de interne elementen. Dit kan leiden tot moeilijk te traceren bugs: wijziging van een genesteld element wordt weerspiegeld in alle "kopieën".
Oplossing: copy.copy() creëert een oppervlakkige kopie (shallow copy) — een nieuwe container op het hoogste niveau, maar de geneste objecten blijven dezelfde. copy.deepcopy() kopieert recursief alle geneste objecten.
Voorbeeldcode:
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]] — het geneste object is gewijzigd! print(deep) # [[1, 2], [3, 4]] — deepcopy heeft de oorspronkelijke toestand behouden
Belangrijke kenmerken:
Is het soms voldoende om lst2 = lst[:] te schrijven voor het kopiëren van een lijst?
lst2 = lst[:] creëert een oppervlakkige kopie van de lijst, maar de geneste objecten (bijvoorbeeld lijsten binnen de lijst) blijven dezelfde. Voor platte lijsten is dit voldoende; voor geneste structuren is dat niet het geval.
Voorbeeld:
lst = [[1], [2]] lst2 = lst[:] lst[0][0] = 99 print(lst2) # [[99], [2]] — het geneste element is gewijzigd in beide "kopieën"
Werkt de methode .copy() hetzelfde voor alle verzamelingen?
Nee. Bijvoorbeeld, dict.copy() werkt als oppervlakkig kopiëren, list.copy() is pas beschikbaar sinds Python 3.3, en voor set is er set.copy(). Voor gebruikersobjecten hangt de ondersteuning van .copy() af van de geïmplementeerde methode.
Kun je overal deepcopy gebruiken? Is dat veilig en efficiënt?
Nee. deepcopy is een kostbare operatie: het kan prestatieproblemen veroorzaken, vooral bij grote structuren, en het faalt bij niet-kopieerbare/sluitende of niet-standaard objecten. Gebruik deepcopy alleen wanneer je echt een volledig onafhankelijke, recursieve kopie nodig hebt.
In tests werden kopieën van een "dictionary van dictionaries" gemaakt via dict.copy(). Hierdoor betroffen wijzigingen in de geneste structuur voor één gebruiker plotseling andere tests (de gegevens mutateerden globaal).
Voordelen:
Nadelen:
We hebben copy.deepcopy() geïmplementeerd, de niveau van genestheid en eigenschappen van de structuur van elk object in de documentatie beschreven, en deepcopy vermeden voor grote volumes waar "handmatige" kopieën per deel mogelijk waren.
Voordelen:
Nadelen: