ProgrammationDéveloppeur Backend

Quelle est la différence entre une copie superficielle et une copie profonde dans une structure dict, et comment copier correctement des dictionnaires imbriqués en Python ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question

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.

Problème

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.

Solution

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 :

  • La copie superficielle ne copie que la première "couche" de l'objet
  • La copie profonde copie récursivement tous les objets à l'intérieur de la structure
  • Lors de la manipulation de structures imbriquées, utilisez toujours deepcopy si une indépendance totale de la copie est nécessaire

Questions pièges.

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

Erreurs typiques et anti-modèles

  • Utilisation d'une simple affectation au lieu d'une copie
  • Application d'une copie superficielle à des structures imbriquées, ce qui entraîne des modifications inattendues dans toutes les "copies"

Exemple de la vie réelle

** 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.