Historique de la question : En Python, la copie d'objets (en particulier des collections - listes, dictionnaires) est critique : une simple attribution à une variable crée une nouvelle référence, pas une copie. Les méthodes spéciales copy() et deepcopy() sont apparues pour éviter les "effets secondaires" indésirables lors de l'utilisation conjointe de structures.
Problème : Lors de la manipulation de collections imbriquées (liste de listes, dictionnaire dans un dictionnaire), un simple copy() reproduit uniquement le conteneur lui-même, mais pas les éléments internes. Cela peut entraîner des bugs difficiles à détecter : la modification d'un élément imbriqué se reflète dans toutes les "copies".
Solution : copy.copy() crée une copie superficielle (shallow copy) - un nouveau conteneur de premier niveau, mais les objets imbriqués restent les mêmes. copy.deepcopy() copie récursivement tous les objets imbriqués.
Exemple de code :
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]] — l'objet imbriqué a changé ! print(deep) # [[1, 2], [3, 4]] — deepcopy a conservé l'état initial
Caractéristiques clés :
Est-il parfois suffisant d'écrire lst2 = lst[:] pour copier une liste ?
lst2 = lst[:] crée une copie superficielle de la liste, mais les objets imbriqués (par exemple, des listes à l'intérieur de la liste) resteront les mêmes. Pour des listes plates - cela suffit ; pour des structures imbriquées - ce n'est pas le cas.
Exemple :
lst = [[1], [2]] lst2 = lst[:] lst[0][0] = 99 print(lst2) # [[99], [2]] — l'élément imbriqué a changé dans les deux "copys"
La méthode .copy() fonctionne-t-elle de la même manière pour toutes les collections ?
Non. Par exemple, dict.copy() fonctionne comme une copie superficielle, list.copy() n'est apparu qu'avec Python 3.3, pour set - il y a set.copy(). Pour les objets personnalisés, le support de .copy() dépend de la méthode implémentée.
Peut-on se passer de deepcopy partout ? Est-ce sûr et efficace ?
Non. deepcopy est une opération coûteuse : elle peut provoquer des problèmes de performance, surtout sur de grandes structures, et elle échoue sur des objets non copiables/fermant ou non standards. Utilisez deepcopy seulement quand vous avez vraiment besoin d'une copie entièrement indépendante et récursive.
Dans les tests, une copie d'un "dictionnaire de dictionnaires" a été réalisée via dict.copy(). En raison de cela, des modifications dans la structure imbriquée pour un utilisateur ont soudainement affecté d'autres tests (les données étaient mutées globalement).
Avantages :
Inconvénients :
Nous avons intégré copy.deepcopy(), décrit dans la documentation le niveau d'imbrication et les caractéristiques de la structure de chaque objet, évité deepcopy pour de gros volumes, où une "copie manuelle" par morceaux était possible.
Avantages :
Inconvénients :