En Python, la structure de données dict est souvent utilisée pour stocker des informations imbriquées. Les développeurs se heurtent fréquemment à la nécessité de cloner de telles structures lors de la manipulation de modèles, de configurations ou du transfert de données entre différentes parties de l'application.
La copie standard d'un dict par affectation (=) ne crée qu'une référence à l'objet d'origine. Une copie superficielle (shallow copy) copie uniquement l'objet dict lui-même, mais pas les objets imbriqués. Une copie profonde (deep copy) copie récursivement tous les objets à l'intérieur, empêchant ainsi les modifications dans une copie d'affecter l'autre.
Pour une copie superficielle, vous pouvez utiliser dict.copy() ou le constructeur dict(), pour une copie profonde — le module copy et la fonction deepcopy() :
import copy d = {"a": 1, "b": {"c": 2}} shallow_d = d.copy() deep_d = copy.deepcopy(d) # Maintenant, modifier shallow_d['b']['c'] affectera d['b']['c'] # modifier deep_d['b']['c'] n'affectera pas le dictionnaire d'origine
Caractéristiques clés :
dict.copy() peut-il copier des niveaux plus profonds ?
Non, dict.copy() crée uniquement une copie superficielle. Les dictionnaires imbriqués seront toujours des références aux mêmes objets que dans le dict d'origine.
Si la structure contient un objet immutable (par exemple, un tuple), la deepcopy va-t-elle le copier profondément ?
Deepcopy ne copie que les objets imbriqués modifiables. Les objets immuables restent les mêmes — les tuples, les chaînes et les nombres ne sont pas copiés de manière récursive, mais sont simplement transférés dans la copie.
Peut-on utiliser la sérialisation via json.loads(json.dumps(dict)) pour une copie profonde ?
Oui, mais avec des réserves. Cette méthode ne fonctionne que pour des types sérialisables et n'est pas adaptée si le dictionnaire contient des objets non sérialisables (par exemple, des fonctions ou des classes personnalisées) :
import json orig = {"a": 10, "b": [1,2,3]} copy_like_deep = json.loads(json.dumps(orig)) # Ne fonctionne pas pour des objets complexes
** Cas négatif
Un développeur clone les paramètres via copy(), puis modifie une valeur imbriquée, pensant qu'il s'agit de deux structures indépendantes.
Avantages :
Simple et rapide
Inconvénients :
Les modifications des objets imbriqués dans une copie se répercutent sur toutes — des bogues difficiles à déboguer.
** Cas positif
Un développeur utilise toujours copy.deepcopy() pour des structures imbriquées, même si le dict d'origine semble plat.
Avantages :
Indépendance des données garantie, les bogues sont réduits au minimum
Inconvénients :
Deepcopy est plus lent et consomme plus de mémoire, parfois excessif.