recorrer - Copia profunda de un dict en python
lista dentro de un diccionario python (4)
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 "<stdin>", line 1, in <module>
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.
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 intento 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.
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
>>>
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 anidados. 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 los posibles escollos ... ejemplo final:
import copy
my_copy2 = copy.deepcopy( my_dict3 )
my_dict1[''b'']=''99''
my_copy2
Out[46]: {''b'': {''b'': ''z''}, ''c'': {''c'': 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 puedes usar deepcopy como se mencionó anteriormente.