ProgramaciónDesarrollador Backend

¿Cuál es la diferencia entre shallow y deep copy en la estructura dict, y cómo copiar correctamente diccionarios anidados en Python?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Historia de la pregunta

En Python, la estructura de datos dict se utiliza a menudo para almacenar información anidada. La necesidad de clonar tales estructuras a menudo se enfrenta a los desarrolladores al trabajar con plantillas, configuraciones o al transferir datos entre partes de la aplicación.

Problema

La copia estándar de dict mediante asignación (=) crea solo una referencia al objeto original. La copia superficial (shallow copy) copia el propio objeto dict, pero no los objetos anidados. La copia profunda (deep copy) copia de forma recursiva todos los objetos dentro, lo que evita que los cambios en una copia afecten a la otra.

Solución

Para la copia superficial se puede usar dict.copy() o el constructor dict(), para la profunda — el módulo copy y la función deepcopy():

import copy d = {"a": 1, "b": {"c": 2}} shallow_d = d.copy() deep_d = copy.deepcopy(d) # Ahora cambiar shallow_d['b']['c'] afectará a d['b']['c'] # cambiar deep_d['b']['c'] no afectará al diccionario original

Características clave:

  • La copia superficial copia solo la primera "capa" del objeto
  • La copia profunda copia recursivamente todos los objetos dentro de la estructura
  • Al trabajar con estructuras anidadas, siempre use deepcopy si se requiere total independencia de la copia

Preguntas trampa.

¿Puede dict.copy() copiar niveles más profundos que el primer nivel?

No, dict.copy() solo crea una copia superficial. Los diccionarios anidados aún serán referencias a los mismos objetos que en el dict original.

Si hay un objeto inmutable en la estructura (por ejemplo, una tupla), ¿deepcopy lo copiará profundamente?

Deepcopy solo copia objetos anidados mutables. Los objetos inmutables permanecen iguales: las tuplas, cadenas y números no se copian recursivamente, sino que se trasladan a la copia.

¿Se puede usar la serialización a través de json.loads(json.dumps(dict)) para la copia profunda?

Se puede, pero con reservas. Este método solo funciona para tipos serializables y no es adecuado si hay objetos no serializables en el diccionario (como funciones o clases personalizadas):

import json orig = {"a": 10, "b": [1,2,3]} copy_like_deep = json.loads(json.dumps(orig)) # No funciona para objetos complejos

Errores típicos y anti-patrones

  • Uso de asignación simple en lugar de copia
  • Aplicación de copia superficial a estructuras anidadas, lo que lleva a cambios inesperados en todas las "copias"

Ejemplo de la vida real

** Caso negativo Un desarrollador clona la configuración a través de copy(), luego cambia un valor anidado, creyendo que son dos estructuras independientes. Pros: Fácil y rápido Contras: Los cambios en los objetos anidados en una copia se reflejan en todos — errores, difíciles de depurar. ** Caso positivo Un desarrollador siempre utiliza copy.deepcopy() para estructuras anidadas, incluso si el dict original parece plano. Pros: Independencia de datos garantizada, errores minimizados Contras: Deepcopy es más lento y consume más memoria, a veces es excesivo.