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