variable deepcopy deepclone python

python - deepclone - deepcopy()



¿Comprender dict.copy()-superficial o profunda? (7)

"nuevo" y "original" son dictados diferentes, por eso puede actualizar solo uno de ellos. Los elementos se copian de forma superficial, no el dictado en sí.

Al leer la documentación de dict.copy() , dice que hace una copia superficial del diccionario. Lo mismo ocurre con el libro que estoy siguiendo (Referencia de Pyzon de Beazley), que dice:

El método m.copy () hace una copia superficial de los elementos contenidos en un objeto de mapeo y los coloca en un nuevo objeto de mapeo.

Considera esto:

>>> original = dict(a=1, b=2) >>> new = original.copy() >>> new.update({''c'': 3}) >>> original {''a'': 1, ''b'': 2} >>> new {''a'': 1, ''c'': 3, ''b'': 2}

Así que asumí que esto actualizaría el valor del original (y agregaría ''c'': 3) también, ya que estaba haciendo una copia superficial. Al igual que si lo haces por una lista:

>>> original = [1, 2, 3] >>> new = original >>> new.append(4) >>> new, original ([1, 2, 3, 4], [1, 2, 3, 4])

Esto funciona como se esperaba.

Dado que ambas son copias poco profundas, ¿por qué es que la dict.copy() no funciona como espero? ¿O mi comprensión de la copia superficial contra la profunda es defectuosa?


Añadiendo a la respuesta de Kennytm. Cuando haces una copia superficial parent.copy (), se crea un nuevo diccionario con las mismas claves, pero los valores no se copian, se les hace referencia. Si agrega un nuevo valor a parent_copy, no tendrá efecto primario porque parent_copy es un nuevo diccionario no referencia.

parent = {1: [1,2,3]} parent_copy = parent.copy() parent_reference = parent print id(parent),id(parent_copy),id(parent_reference) #140690938288400 140690938290536 140690938288400 print id(parent[1]),id(parent_copy[1]),id(parent_reference[1]) #140690938137128 140690938137128 140690938137128 parent_copy[1].append(4) parent_copy[2] = [''new''] print parent, parent_copy, parent_reference #{1: [1, 2, 3, 4]} {1: [1, 2, 3, 4], 2: [''new'']} {1: [1, 2, 3, 4]}

El valor de hash (id) de parent [1] , parent_copy [1] es idéntico, lo que implica [1,2,3] de parent [1] y parent_copy [1] almacenado en la id 140690938288400.

Pero el hash de parent y parent_copy son diferentes, lo que implica que son diccionarios diferentes y parent_copy es un nuevo diccionario que tiene valores de referencia a valores de parent


En su segunda parte, debe usar new = original.copy()

.copy y = son cosas diferentes.


No es una cuestión de copia profunda o copia superficial, nada de lo que estás haciendo es una copia profunda.

Aquí:

>>> new = original

está creando una nueva referencia a la lista / dict que hace referencia el original.

mientras que aquí:

>>> new = original.copy() >>> # or >>> new = list(original) # dict(original)

está creando una nueva lista / dict que se rellena con una copia de las referencias de los objetos contenidos en el contenedor original.


Por "copia superficial" significa que el contenido del diccionario no se copia por valor, sino que se crea una nueva referencia.

>>> a = {1: [1,2,3]} >>> b = a.copy() >>> a, b ({1: [1, 2, 3]}, {1: [1, 2, 3]}) >>> a[1].append(4) >>> a, b ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})

En contraste, una copia profunda copiará todos los contenidos por valor.

>>> import copy >>> c = copy.deepcopy(a) >>> a, c ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]}) >>> a[1].append(5) >>> a, c ({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})

Asi que:

  1. b = a : Asignación de referencia, Make a y b apunta al mismo objeto.

  2. b = a.copy() : b = a.copy() superficial, a y b se convertirán en dos objetos aislados, pero sus contenidos aún comparten la misma referencia

  3. b = copy.deepcopy(a) : b = copy.deepcopy(a) profunda, la estructura y el contenido de b quedan completamente aislados.


Tomemos este ejemplo:

original = dict(a=1, b=2, c=dict(d=4, e=5)) new = original.copy()

Ahora cambiemos un valor en el nivel ''superficial'' (primer nivel):

new[''a''] = 10 # new = {''a'': 10, ''b'': 2, ''c'': {''d'': 4, ''e'': 5}} # original = {''a'': 1, ''b'': 2, ''c'': {''d'': 4, ''e'': 5}} # no change in original, since [''a''] is an immutable integer

Ahora vamos a cambiar un valor un nivel más profundo:

new[''c''][''d''] = 40 # new = {''a'': 10, ''b'': 2, ''c'': {''d'': 40, ''e'': 5}} # original = {''a'': 1, ''b'': 2, ''c'': {''d'': 40, ''e'': 5}} # new[''c''] points to the same original[''d''] mutable dictionary, so it will be changed


Los contenidos son poco profundos copiados.

Por lo tanto, si el dict original contiene una list u otro dictionary , modificarlos en el original o su copia superficial los modificará (la list o el dict ) en el otro.