Copia profunda de un dict en python

Me gustaría hacer una copia profunda de un dict en python. Desafortunadamente, el método .deepcopy() no existe para el dict . ¿Cómo puedo hacer eso?

 >>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]} >>> my_copy = my_dict.deepcopy() Traceback (most recent calll last): File "", line 1, in  AttributeError: 'dict' object has no attribute 'deepcopy' >>> my_copy = my_dict.copy() >>> my_dict['a'][2] = 7 >>> my_copy['a'][2] 7 

La última línea debe ser 3 .

Me gustaría que las modificaciones en my_dict no afecten la instantánea my_copy .

¿Cómo puedo hacer eso? La solución debe ser compatible con Python 3.x.

Related of "Copia profunda de un dict en python"

Qué tal si:

 import copy d = { ... } d2 = copy.deepcopy(d) 

Python 2 o 3:

 Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import copy >>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]} >>> my_copy = copy.deepcopy(my_dict) >>> my_dict['a'][2] = 7 >>> my_copy['a'][2] 3 >>> 

dict.copy () es una función de copia superficial para diccionario
ID es una función incorporada que le da la dirección de la variable

Primero debes entender “¿por qué está ocurriendo este problema en particular?”

 In [1]: my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]} In [2]: my_copy = my_dict.copy() In [3]: id(my_dict) Out[3]: 140190444167808 In [4]: id(my_copy) Out[4]: 140190444170328 In [5]: id(my_copy['a']) Out[5]: 140190444024104 In [6]: id(my_dict['a']) Out[6]: 140190444024104 

La dirección de la lista presente en ambos dictados para la clave ‘a’ está apuntando a la misma ubicación.
Por lo tanto, cuando cambia el valor de la lista en my_dict, la lista en my_copy también cambia.


Solución:

 In [7]: my_copy = {key: value[:] for key, value in my_dict.items()} In [8]: id(my_copy['a']) Out[8]: 140190444024176 

O puede utilizar la copia en profundidad como se mencionó anteriormente.

Python 3.x

desde copia importada en copia profunda

 my_dict = {'one': 1, 'two': 2} new_dict_deepcopy = deepcopy(my_dict) 

Sin la copia en profundidad, no puedo eliminar el diccionario de nombre de host dentro del diccionario de mi dominio.

Sin deepcopy me sale el siguiente error:

 "RuntimeError: dictionary changed size during iteration" 

… cuando bash eliminar el elemento deseado de mi diccionario dentro de otro diccionario.

 import socket import xml.etree.ElementTree as ET from copy import deepcopy 

dominio es un objeto de diccionario

 def remove_hostname(domain, hostname): domain_copy = deepcopy(domain) for domains, hosts in domain_copy.items(): for host, port in hosts.items(): if host == hostname: del domain[domains][host] return domain 

Salida de ejemplo: [original] dominios = {‘dominio local’: {‘localhost’: {‘todos’: ‘4000’}}}

[new] domains = {‘localdomain’: {}}}

Entonces, lo que está sucediendo aquí es que estoy iterando sobre una copia de un diccionario en lugar de hacerlo sobre el mismo diccionario. Con este método, puedes eliminar elementos según sea necesario.

Una solución más simple (en mi opinión) es crear un nuevo diccionario y actualizarlo con el contenido del anterior:

 my_dict={'a':1} my_copy = {} my_copy.update( my_dict ) my_dict['a']=2 my_dict['a'] Out[34]: 2 my_copy['a'] Out[35]: 1 

El problema con este enfoque es que puede no ser “lo suficientemente profundo”. Es decir, no es recursivamente profundo. Suficientemente bueno para objetos simples pero no para diccionarios nesteds. Aquí hay un ejemplo donde puede que no sea lo suficientemente profundo:

 my_dict1={'b':2} my_dict2={'c':3} my_dict3={ 'b': my_dict1, 'c':my_dict2 } my_copy = {} my_copy.update( my_dict3 ) my_dict1['b']='z' my_copy Out[42]: {'b': {'b': 'z'}, 'c': {'c': 3}} 

Al usar Deepcopy () puedo eliminar el comportamiento semi-superficial, pero creo que uno debe decidir qué enfoque es el adecuado para su aplicación. En la mayoría de los casos, es posible que no le importe, pero debe tener en cuenta las posibles dificultades … Ejemplo final:

 import copy my_copy2 = copy.deepcopy( my_dict3 ) my_dict1['b']='99' my_copy2 Out[46]: {'b': {'b': 'z'}, 'c': {'c': 3}}