Cómo copiar un diccionario y solo editar la copia

1111

¿Alguien puede explicarme esto? Esto no tiene ningún sentido para mí.

Copio un diccionario en otro y edito el segundo y ambos se cambian. ¿Por qué está pasando esto?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
2
1093

Python nunca copia objetos implícitamente. Cuando lo configura dict2 = dict1, está haciendo que se refieran al mismo objeto dict exacto, por lo que cuando lo mute, todas las referencias siguen refiriéndose al objeto en su estado actual.

Si desea copiar el dict (que es raro), debe hacerlo explícitamente con

dict2 = dict(dict1)

o

dict2 = dict1.copy()
31
  • 40
    Podría ser mejor decir "dict2 y dict1 apuntan al mismo diccionario", no estás cambiando dict1 o dict2 sino a lo que apuntan. 17/03/10 a las 21:15
  • 360
    También tenga en cuenta que el dict.copy () es superficial, si hay una lista anidada / etc, los cambios se aplicarán a ambos. IIRC. Deepcopy evitará eso.
    Will
    18 de marzo de 2010 a las 7:08
  • 20
    No es del todo correcto que Python nunca copie objetos implícitamente. Los tipos de datos primitivos, como int, float y bool, también se tratan como objetos (solo haga a dir(1)para ver eso), pero se copian implícitamente. 6/03/12 a las 10:34
  • 22
    @danielkullmann, creo que es posible que tenga malentendidos sobre Python en función de cómo funcionan otros lenguajes con los que ha tratado. En Python, a) No existe el concepto de "tipos de datos primitivos". int, floaty las boolinstancias son objetos reales de Python, yb) los objetos de estos tipos no se copian implícitamente cuando los pasa, no a un nivel semántico de Python con seguridad y ni siquiera como un detalle de implementación en CPython. 6 mar. 12 a las 15:03
  • 84
    La retórica sin fundamento como "La copia profunda se considera dañina" es inútil. En igualdad de condiciones, es mucho más probable que la copia superficial de una estructura de datos compleja produzca problemas inesperados de casos extremos que la copia profunda de la misma estructura. Una copia en la que las modificaciones modifican el objeto original no es una copia; es un error. Ergo, la mayoría de los casos de uso deberían llamar en copy.deepcopy()lugar de dict()o dict.copy(). La respuesta concisa de Imran está en el lado correcto de la cordura, a diferencia de esta respuesta. 5 de diciembre de 2017 a las 3:39
856

Cuando asigna dict2 = dict1, no está haciendo una copia de dict1, resulta en dict2ser solo otro nombre para dict1.

Para copiar los tipos mutables como diccionarios, use copy/ deepcopydel copymódulo.

import copy

dict2 = copy.deepcopy(dict1)
8
  • 111
    Para cualquier diccionario con el que trabaje, deepcopy es lo que necesito ... Acabo de perder varias horas debido a un error que se debió a que no obtenía una copia completa de un diccionario anidado y mis cambios en las entradas anidadas estaban afectando al original. . 12/04/2014 a las 23:01
  • 11
    Aquí igual. deepcopy () hace el truco. Estaba estropeando mis dictados anidados dentro de un caché giratorio al agregar una marca de tiempo a una 'copia' del evento original. ¡Gracias!
    fxstein
    10 feb 2015 a las 3:05
  • 12
    En realidad, esto debería marcarse como la respuesta correcta; Esta respuesta es general y también funciona para un diccionario de diccionarios. 14 de agosto de 2016 a las 12:09
  • 50
    Esta debería ser la respuesta aceptada. La retórica infundada de "La copia profunda se considera dañina" incrustada en la sección de comentarios de la respuesta aceptada actual invita descaradamente a problemas de sincronización al copiar diccionarios anidados (como los que se documentan aquí) y debe ser cuestionada como tal. 5 de diciembre de 2017 a las 3:44
  • 1
    deepcopy es el camino a seguir en caso de una estructura de diccionario compleja. dict1.copy () simplemente copia los valores de las claves como referencias y no como objetos. 2 mar.20 a las 13:51
238

Si bien dict.copy()y dict(dict1)genera una copia, solo son copias superficiales . Si desea una copia profunda , copy.deepcopy(dict1)se requiere. Un ejemplo:

>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = x.copy()
>>> copy2 = dict(x)
>>> import copy
>>> copy3 = copy.deepcopy(x)
>>> source['a'] = 10  # a change to first-level properties won't affect copies
>>> source
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy3
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> source['b']['m'] = 40  # a change to deep properties WILL affect shallow copies 'b.m' property
>>> source
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy3  # Deep copy's 'b.m' property is unaffected
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}

Con respecto a las copias superficiales frente a las profundas, de los documentos del módulo de Pythoncopy :

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
4
  • 3
    esta debería ser la respuesta correcta, ya que no se repite explícitamente sobre el dict y se puede usar para otras estructuras primarias. 22 de enero de 2015 a las 12:23
  • 33
    Solo para aclarar: w=copy.deepcopy(x)es la línea clave. 23 de septiembre de 2015 a las 14:06
  • ¿Cuál es la diferencia entre dict2 = dict1y dict2 = copy.deepcopy(dict1)?
    TheTank
    1 de junio de 2018 a las 14:41
  • 1
    @TheTank, y = x hace que los dos nombres (referencias) se refieran a un mismo objeto, es decir, "y es x" es Verdadero. Cualquier cambio realizado en el objeto a través de x es equivalente a un mismo cambio a través de y. Sin embargo, u, v, w son referencias a nuevos objetos diferentes que tienen valores copiados de x durante la instanciación. En cuanto a las diferencias entre u, v (copia superficial) y w (copia profunda), consulte docs.python.org/2/library/copy.html
    gpanda
    2 de junio de 2018 a las 8:32
73

En python 3.5+ hay una manera más fácil de lograr una copia superficial usando el operador de desempaquetado **. Definido por Pep 448 .

>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}

** descomprime el diccionario en un nuevo diccionario que luego se asigna a dict2.

También podemos confirmar que cada diccionario tiene una identificación distinta.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Si se necesita una copia profunda, copy.deepcopy () sigue siendo el camino a seguir.

6
  • 3
    Esto se parece terriblemente a punteros en C ++. Agradable para realizar la tarea, pero en cuanto a legibilidad, tiendo a no gustarme este tipo de operadores.
    Ernesto
    12 sep 2017 a las 17:00
  • 1
    Tiene una especie de apariencia elegante ... pero cuando se combinan varios diccionarios, la sintaxis se ve bastante fluida. 12 sep 2017 a las 17:17
  • 3
    Tenga cuidado con eso, solo realiza una copia superficial. 29 de enero de 2018 a las 11:17
  • tienes razón @SebastianDressler, haré ajustes. gracias. 29 de enero de 2018 a las 14:06
  • 4
    Útil si desea crear una copia con algunas especias: dict2 = {**dict1, 'key3':'value3'}
    evg656e
    21 de septiembre de 2018 a las 23:33
70

En profundidad y una forma fácil de recordar:

Siempre que haga dict2 = dict1, dict2 se refiere a dict1. Tanto dict1 como dict2 apuntan a la misma ubicación en la memoria. Este es solo un caso normal al trabajar con objetos mutables en Python. Cuando trabaje con objetos mutables en Python, debe tener cuidado ya que es difícil de depurar.

En lugar de usar dict2 = dict1, debería usar el método copy ( copia superficial) y deepcopy del módulo de copia de python para separar dict2 de dict1.

La forma correcta es:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?"
>>> dict2
{'key1': 'value1', 'key2': 'WHY?'}
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>> id(dict1)
140641178056312
>>> id(dict2)
140641176198960
>>> 

Como puede ver, la identificación de dict1 y dict2 son diferentes, lo que significa que ambos apuntan / hacen referencia a diferentes ubicaciones en la memoria.

Esta solución funciona para diccionarios con valores inmutables, esta no es la solución correcta para aquellos con valores mutables.

P.ej:

>>> import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': False}}
>>> id(dict1)
140641197660704
>>> id(dict2)
140641196407832
>>> id(dict1["key2"])
140641176198960
>>> id(dict2["key2"])
140641176198960

Puede ver que aunque aplicamos copy para dict1, el valor de mutable se cambia a falso tanto en dict2 como en dict1 aunque solo lo cambiamos en dict2. Esto se debe a que cambiamos el valor de una parte dict mutable de dict1. Cuando aplicamos una copia en dict, solo hará una copia superficial, lo que significa que copia todos los valores inmutables en un nuevo dict y no copia los valores mutables pero los hará referencia.

La solución definitiva es hacer una copia profunda de dict1 para crear completamente un nuevo dict con todos los valores copiados, incluidos los valores mutables.

>>>import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = copy.deepcopy(dict1)
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> id(dict1)
140641196228824
>>> id(dict2)
140641197662072
>>> id(dict1["key2"])
140641178056312
>>> id(dict2["key2"])
140641197662000
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': True}}

Como puede ver, los id son diferentes, significa que dict2 es un dict completamente nuevo con todos los valores en dict1.

Deepcopy debe usarse si siempre que desea cambiar alguno de los valores mutables sin afectar el dict original. Si no, puede utilizar una copia superficial. Deepcopy es lento, ya que funciona de forma recursiva para copiar cualquier valor anidado en el diccionario original y también requiere memoria adicional.

51

Las mejores y más fáciles formas de crear una copia de un dictado en Python 2.7 y 3 son ...

Para crear una copia de un diccionario simple (de un solo nivel):

1. Usando el método dict () , en lugar de generar una referencia que apunte al dict existente.

my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1)  # {'message':'Hello Python'}

my_dict2 = dict(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

2. Usando el método incorporado update () del diccionario de Python.

my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

Para crear una copia de un diccionario anidado o complejo:

Utilice el módulo de copia incorporado , que proporciona operaciones de copia genéricas superficiales y profundas. Este módulo está presente tanto en Python 2.7 como en 3. *

import copy

my_dict2 = copy.deepcopy(my_dict1)
2
  • 6
    Creo que dict()crea una copia superficial, no una copia profunda. Lo que significa que si tiene un código anidado dict, el exterior dictserá una copia, pero el código interno será una referencia al código interno original.
    shmuels
    10/07/18 a las 15:13
  • @shmuels sí, ambos métodos crearán una copia superficial, no profunda. Mira, la respuesta actualizada. 16/07/18 a las 14:12
38

También puede crear un nuevo diccionario con una comprensión de diccionario. Esto evita importar una copia.

dout = dict((k,v) for k,v in mydict.items())

Por supuesto, en python> = 2.7 puedes hacer:

dout = {k:v for k,v in mydict.items()}

Pero para la compatibilidad con versiones anteriores, el método superior es mejor.

4
  • 4
    Esto es particularmente útil si desea tener más control sobre cómo y qué se copia exactamente. +1 26/01/15 a las 5:43
  • 15
    Tenga en cuenta que este método no realiza una copia profunda, y si desea una copia superficial sin necesidad de controlar las claves que se van a copiar, d2 = dict.copy(d1)tampoco requiere ninguna importación. 23/08/15 a las 23:23
  • 1
    @ JarekPiórkowski: o puede llamar a un método como un método: d2 = d1.copy() 24 nov 2018 a las 7:50
  • Tenga en cuenta que no necesita la comprensión del primer ejemplo. dict.itemsya devuelve un par clave / valor iterable. Entonces puede usar dict(mydict.items())(también puede usar dict(mydict)). Puede ser útil tener la comprensión si desea filtrar las entradas. 11 de mayo de 2020 a las 23:39
31

Además de las otras soluciones proporcionadas, puede utilizar **para integrar el diccionario en un diccionario vacío, por ejemplo,

shallow_copy_of_other_dict = {**other_dict}.

Ahora tendrá una copia "superficial" de other_dict.

Aplicado a tu ejemplo:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = {**dict1}
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>>

Puntero: diferencia entre copys superficiales y profundos

2
  • 1
    Esto da como resultado una copia superficial, no una copia profunda.
    sytech
    23/11/18 a las 23:47
  • 1
    Estaba intentando esto pero tenía problemas. Esto solo funciona para Python 3.5 y versiones posteriores. python.org/dev/peps/pep-0448 13/12/18 a las 18:25
21

Las declaraciones de asignación en Python no copian objetos, crean enlaces entre un objetivo y un objeto.

entonces, dict2 = dict1resulta otro enlace entre dict2y el objeto al que se dict1refiere.

si desea copiar un dictado, puede usar el copy module. El módulo de copia tiene dos interfaces:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

La diferencia entre copia superficial y profunda solo es relevante para objetos compuestos (objetos que contienen otros objetos, como listas o instancias de clase):

Una copia superficial construye un nuevo objeto compuesto y luego (en la medida de lo posible) inserta en él referencias a los objetos que se encuentran en el original.

Una copia profunda construye un nuevo objeto compuesto y luego, de forma recursiva, inserta copias en él de los objetos encontrados en el original.

Por ejemplo, en python 2.7.9:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

y el resultado es:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]
12

Esto también me confundió, inicialmente, porque venía de un entorno C.

En C, una variable es una ubicación en la memoria con un tipo definido. La asignación a una variable copia los datos en la ubicación de la memoria de la variable.

Pero en Python, las variables actúan más como punteros a objetos. Entonces, asignar una variable a otra no hace una copia, solo hace que el nombre de la variable apunte al mismo objeto.

3
  • 6
    las variables de Python actúan más como referencias de C ++ 18 de marzo de 2010 a las 8:58
  • 7
    ¡Porque todo en Python es un objeto! diveintopython.net/getting_to_know_python/… (sí, esta respuesta tiene muchos años de retraso, ¡pero quizás sea de alguna utilidad para alguien!)
    grimman
    23/11/2013 a las 12:24
  • 2
    Creo que la semántica del lenguaje Python dice que no hay "variables". Se denominan "referencias con nombre"; lo que significa que la referencia a un objeto es una cadena sintáctica en código. Un objeto puede tener muchas referencias con nombre. Los objetos inmutables como ints y floats e instancias str tienen solo una instancia por proceso. Un int de 1 en la memoria no cambia a 2 o algún otro valor en la misma dirección de memoria cuando haces esto myvalue = 1 myvalue = 2 24 de junio de 2016 a las 2:03
11

Puede copiar y editar la copia recién construida de una sola vez llamando al dictconstructor con argumentos de palabras clave adicionales:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
0
8

Cada variable en Python (cosas como dict1o stro __builtins__es un puntero a algún "objeto" platónico oculto dentro de la máquina.

Si lo configura dict1 = dict2, simplemente apunte dict1al mismo objeto (o ubicación de memoria, o cualquier analogía que desee) que dict2. Ahora, el objeto al que hace referencia dict1es el mismo objeto al que hace referencia dict2.

Puede comprobar: dict1 is dict2debería ser True. Además, id(dict1)debería ser el mismo que id(dict2).

Quieres dict1 = copy(dict2), o dict1 = deepcopy(dict2).

¿La diferencia entre copyy deepcopy? deepcopyse asegurará de que los elementos de dict2(¿lo apuntó a una lista?) también sean copias.

No uso deepcopymucho; por lo general, es una mala práctica escribir código que lo necesite (en mi opinión).

1
  • Me acabo de dar cuenta de que siempre necesito usar deepcopy para que cuando copie un diccionario anidado y empiece a modificar entradas anidadas, los efectos ocurran solo en la copia y no en el original. 12/04/2014 a las 23:04
7

dict1es un símbolo que hace referencia a un objeto de diccionario subyacente. La asignación dict1a dict2simplemente asigna la misma referencia. Cambiar el valor de una clave a través del dict2símbolo cambia el objeto subyacente, lo que también afecta dict1. Esto es confuso.

Es mucho más fácil razonar sobre valores inmutables que referencias, así que haga copias siempre que sea posible:

person = {'name': 'Mary', 'age': 25}
one_year_later = {**person, 'age': 26}  # does not mutate person dict

Esto es sintácticamente lo mismo que:

one_year_later = dict(person, age=26)
6
>>> dict2 = dict1
# dict2 is bind to the same Dict object which binds to dict1, so if you modify dict2, you will modify the dict1

Hay muchas formas de copiar un objeto Dict, yo simplemente uso

dict_1 = {
           'a':1,
           'b':2
         }
dict_2 = {}
dict_2.update(dict_1)
2
  • 13
    dict_2 = dict_1.copy() es mucho más eficiente y lógico. 2/01/19 a las 14:40
  • 2
    Tenga en cuenta que si tiene un dict dentro de dict1, con dict_1.copy () los cambios que realiza en el dict interno en dict_2 también se aplican al dict interno en dict_1. En este caso, debería utilizar copy.deepcopy (dict_1) en su lugar.
    queise
    15/04/19 a las 17:27
5

dict2 = dict1no copia el diccionario. Simplemente le da al programador una segunda forma ( dict2) de referirse al mismo diccionario.

1

Como han explicado otros, el incorporado dictno hace lo que quieres. Pero en Python2 (y probablemente también en 3) puede crear fácilmente una ValueDictclase con la que se copia =para que pueda estar seguro de que el original no cambiará.

class ValueDict(dict):

    def __ilshift__(self, args):
        result = ValueDict(self)
        if isinstance(args, dict):
            dict.update(result, args)
        else:
            dict.__setitem__(result, *args)
        return result # Pythonic LVALUE modification

    def __irshift__(self, args):
        result = ValueDict(self)
        dict.__delitem__(result, args)
        return result # Pythonic LVALUE modification

    def __setitem__(self, k, v):
        raise AttributeError, \
            "Use \"value_dict<<='%s', ...\" instead of \"d[%s] = ...\"" % (k,k)

    def __delitem__(self, k):
        raise AttributeError, \
            "Use \"value_dict>>='%s'\" instead of \"del d[%s]" % (k,k)

    def update(self, d2):
        raise AttributeError, \
            "Use \"value_dict<<=dict2\" instead of \"value_dict.update(dict2)\""


# test
d = ValueDict()

d <<='apples', 5
d <<='pears', 8
print "d =", d

e = d
e <<='bananas', 1
print "e =", e
print "d =", d

d >>='pears'
print "d =", d
d <<={'blueberries': 2, 'watermelons': 315}
print "d =", d
print "e =", e
print "e['bananas'] =", e['bananas']


# result
d = {'apples': 5, 'pears': 8}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
d = {'apples': 5, 'pears': 8}
d = {'apples': 5}
d = {'watermelons': 315, 'blueberries': 2, 'apples': 5}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
e['bananas'] = 1

# e[0]=3
# would give:
# AttributeError: Use "value_dict<<='0', ..." instead of "d[0] = ..."

Consulte el patrón de modificación de lvalue discutido aquí: Python 2.7 - sintaxis limpia para la modificación de lvalue . La observación clave es que stry se intcomportan como valores en Python (aunque en realidad son objetos inmutables bajo el capó). Mientras observa eso, observe también que nada es mágicamente especial en stro int. dictse puede usar de la misma manera, y puedo pensar en muchos casos en los que ValueDicttiene sentido.

1

el siguiente código, que está en dicts que sigue la sintaxis json más de 3 veces más rápido que deepcopy

def CopyDict(dSrc):
    try:
        return json.loads(json.dumps(dSrc))
    except Exception as e:
        Logger.warning("Can't copy dict the preferred way:"+str(dSrc))
        return deepcopy(dSrc)
0

Me encontré con un comportamiento peculiar al intentar copiar en profundidad la propiedad del diccionario de la clase sin asignarla a la variable

new = copy.deepcopy(my_class.a)no funciona, es decir, modificar newmodificamy_class.a

pero si lo hace old = my_class.ay luego new = copy.deepcopy(old)funciona perfectamente, es decir, modificar newno afectamy_class.a

No estoy seguro de por qué sucede esto, ¡pero espero que ayude a ahorrar algunas horas! :)

2
  • Entonces, ¿cómo se hace una copia en profundidad de my_class.a?
    Anthony
    7 feb.20 a las 23:52
  • No es la mejor forma. Buena respuesta es bramido. 23 de mayo de 2020 a las 0:32
-2

Copiando usando un bucle for:

orig = {"X2": 674.5, "X3": 245.0}

copy = {}
for key in orig:
    copy[key] = orig[key]

print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 674.5, 'X3': 245.0}
copy["X2"] = 808
print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 808, 'X3': 245.0}
2
  • 1
    Esto solo funciona para diccionarios simples. ¿Por qué no utilizarlo deepcopy, que está construido expresamente para este fin?
    Anthony
    7 feb.20 a las 23:54
  • No es la mejor forma. Buena respuesta es bramido. 23 de mayo de 2020 a las 0:32
-6

Puedes usar directamente:

dict2 = eval(repr(dict1))

donde el objeto dict2 es una copia independiente de dict1, por lo que puede modificar dict2 sin afectar a dict1.

Esto funciona para cualquier tipo de objeto.

2
  • 4
    Esta respuesta es incorrecta y no debe usarse. Una clase definida por el usuario, por ejemplo, puede no tener un apropiado __repr__para ser reconstruida por eval, ni la clase del objeto puede estar en el ámbito actual para ser llamado. Incluso si se sigue con los tipos integrados, esto fallará si el mismo objeto se almacena en varias claves, ya dict2que tendría dos objetos separados. Un diccionario autorreferencial, donde se dict1contiene a sí mismo, en su lugar contendrá Ellipsis. Sería mejor usardict1.copy() 31/10/2017 a las 17:11
  • No se espera que los objetos (o "valores") tengan siempre una representación fiel mediante cadenas de caracteres, en cualquier caso, no de la forma habitual legible por humanos.
    Alexey
    21 feb 2018 a las 12:50
-6

Otra forma más limpia sería usar json. ver el código a continuación

>>> a = [{"name":"Onkar","Address": {"state":"MH","country":"India","innerAddress":{"city":"Pune"}}}]
>>> b = json.dumps(a)
>>> b = json.loads(b)
>>> id(a)
2334461105416
>>> id(b)
2334461105224
>>> a[0]["Address"]["innerAddress"]["city"]="Nagpur"
>>> a
[{'name': 'Onkar', 'Address': {'state': 'MH', 'country': 'India', 'innerAddress': {'city': 'Nagpur'}}}]
>>> b
[{'name': 'Onkar', 'Address': {'state': 'MH', 'country': 'India', 'innerAddress': {'city': 'Pune'}}}]
>>> id(a[0]["Address"]["innerAddress"])
2334460618376
>>> id(b[0]["Address"]["innerAddress"])
2334424569880

Para crear otro diccionario, haga json.dumps () y luego json.loads () en el mismo objeto de diccionario. Tendrá un objeto dict separado.

1
  • 1
    Esto solo funciona para entradas serializables json e incurre en una gran sobrecarga.
    moi
    6 de enero a las 13:02