La copie superficielle (shallow copy) crée un nouvel objet de niveau supérieur, mais les objets imbriqués (éléments de listes, dictionnaires imbriqués, etc.) partagent la mémoire avec l'original. La copie profonde (deep copy) copie récursivement tous les niveaux des objets.
On peut utiliser le module copy :
import copy original = [[1, 2], [3, 4]] shallow = copy.copy(original) deep = copy.deepcopy(original) shallow[0][0] = 99 # Change à la fois original et shallow print(original) # [[99, 2], [3, 4]] # Maintenant avec deep original = [[1, 2], [3, 4]] deep = copy.deepcopy(original) deep[0][0] = 99 print(original) # [[1, 2], [3, 4]]
copy.copy(obj): ne copie que "l'enveloppe"copy.deepcopy(obj): copie récursive complèteQue se passe-t-il lors de la copie d'un tuple qui contient des objets modifiables ?
tuple est immuable, mais ses éléments peuvent être modifiables (par exemple, une liste). La copie superficielle et la copie profonde diffèrent :
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]) # Lors de la deep copy : t = ([1, 2], [3, 4]) deep = copy.deepcopy(t) deep[0][0] = 88 print(t) # ([1, 2], [3, 4])
Histoire
Dans une application de traitement de documents, les données étaient stockées dans une liste à l'intérieur d'un dictionnaire. Lors de la copie d'objets à l'aide de copy.copy, les éléments imbriqués étaient accidentellement modifiés lors de la modification du nouvel objet. En conséquence, les données d'origine ont été modifiées dans d'autres parties du système ! Cela a causé une corruption de données. Cela a été corrigé en remplaçant par deepcopy.
Histoire
Dans un projet de machine learning, lors de l'enregistrement des hyperparamètres des modèles, nous copions la liste des configurations par affectation standard et shallow copy, après quoi différentes expériences modifiaient mutuellement leurs paramètres. La source du bug a été trouvée après un diagnostic du comportement de la copie des listes imbriquées via deepcopy.
Histoire
Dans un logiciel financier, deep copy a été accidentellement appliqué à un objet incluant un fichier ouvert (handle), ce qui a provoqué TypeError: cannot pickle '_io.TextIOWrapper' object — parce que copy.deepcopy utilise pickle en interne. Cela a été corrigé par un traitement explicite de tels champs ou par un appel à shallow copy.