¿Cuál es la diferencia entre copia superficial, copia profunda y operación de asignación normal?

210
import copy

a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}

a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)


print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))

Obtengo los siguientes resultados:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

Si realizo una copia profunda:

a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)

Los resultados son los mismos:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

Si trabajo en operaciones de asignación:

a1 = a
b1 = b
c1 = c
d1 = d

entonces los resultados son:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True

¿Alguien puede explicar qué hace exactamente la diferencia entre las copias? ¿Es algo relacionado con objetos mutables e inmutables? Si es así, ¿me lo puedes explicar?

deeshank
fuente

Respuestas:

364

Las operaciones de asignación normales simplemente apuntarán la nueva variable hacia el objeto existente. Los documentos explican la diferencia entre copias superficiales y profundas:

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 referencias en él a los objetos encontrados en el original.

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

Aquí hay una pequeña demostración:

import copy

a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]

Usando operaciones de asignación normales para copiar:

d = c

print id(c) == id(d)          # True - d is the same object as c
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

Usando una copia superficial:

d = copy.copy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

Usando una copia profunda:

d = copy.deepcopy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # False - d[0] is now a new object
grc
fuente
55
¿Asignación es lo mismo que copia superficial?
deeshank
35
@Dshank No. Una copia superficial construye un nuevo objeto, mientras que una asignación simplemente apuntará la nueva variable al objeto existente. Cualquier cambio en el objeto existente afectará a ambas variables (con asignación).
grc
13
@grc "Cualquier cambio en el objeto existente afectará a ambas variables (con asignación)" - esta declaración es verdadera solo para objetos mutables y no para tipos inmutables como string, float, tuples.
Neerav
1
@grc Pero he intentado un ejemplo (elimino la nueva línea aquí). list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)La newlistvisualización fija [[1, 2], [3, 4]]. Pero list_[0]es una lista que es mutable.
Alston
1
@Stallman list_[0]es mutable, pero no lo está mutando / modificando. Probar list_[0].append(9)o en su list_[0][0] = 7lugar.
grc
46

Para los objetos inmutables, no hay necesidad de copiar porque los datos nunca cambiarán, por lo que Python usa los mismos datos; Los ID son siempre iguales. Para objetos mutables, dado que pueden cambiar potencialmente, la copia [superficial] crea un nuevo objeto.

La copia profunda está relacionada con estructuras anidadas. Si tiene una lista de listas, entonces realice copiesuna copia profunda de las listas anidadas, por lo que es una copia recursiva. Con solo copiar, tiene una nueva lista externa, pero las listas internas son referencias.

La asignación no se copia. Simplemente establece la referencia a los datos antiguos. Por lo tanto, necesita copiar para crear una nueva lista con el mismo contenido.

perreal
fuente
With just copy, you have a new outer list but inner lists are references.Para las listas internas, ¿estaría el copiado influenciado por el original? Creo una lista de listas como list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]y la newlistsigue siendo la misma, ¿la lista interna son referencias?
Alston
1
@Stallman, no está cambiando la lista referenciada aquí, solo está creando una nueva lista y asignándola como el primer elemento de una de las copias. intente hacerlolist_[0][0] = 7
perreal
20

Para los objetos inmutables, crear una copia no tiene mucho sentido ya que no van a cambiar. Para objetos mutables assignment, copyy se deepcopycomporta de manera diferente. Hablemos de cada uno de ellos con ejemplos.

Una operación de asignación simplemente asigna la referencia de origen a destino, por ejemplo:

>>> i = [1,2,3]
>>> j=i
>>> hex(id(i)), hex(id(j))
>>> ('0x10296f908', '0x10296f908') #Both addresses are identical

Ahora iy jtécnicamente se refiere a la misma lista. Ambos iy jtienen la misma dirección de memoria. Cualquier actualización a cualquiera de ellos se reflejará en el otro. p.ej:

>>> i.append(4)
>>> j
>>> [1,2,3,4] #Destination is updated

>>> j.append(5)
>>> i
>>> [1,2,3,4,5] #Source is updated

Por otro lado copyy deepcopycrea una nueva copia de variable. Por lo tanto, ahora los cambios en la variable original no se reflejarán en la variable de copia y viceversa. Sin embargo copy(shallow copy), no crea una copia de objetos anidados, sino que simplemente copia la referencia de los objetos anidados. Deepcopy copia todos los objetos anidados recursivamente.

Algunos ejemplos para demostrar el comportamiento de copyy deepcopy:

Ejemplo de lista plana usando copy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.copy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

Ejemplo de lista anidada usando copy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.copy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x10296f908') #Nested lists have same address

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5,6]] #Updation of original nested list updated the copy as well

Ejemplo de lista plana usando deepcopy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.deepcopy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

Ejemplo de lista anidada usando deepcopy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.deepcopy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x102b9b7c8') #Nested lists have different addresses

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5]] #Updation of original nested list didn't affected the copied variable    
Sohaib Farooqi
fuente
18

Veamos en un ejemplo gráfico cómo se ejecuta el siguiente código:

import copy

class Foo(object):
    def __init__(self):
        pass


a = [Foo(), Foo()]
shallow = copy.copy(a)
deep = copy.deepcopy(a)

ingrese la descripción de la imagen aquí

usuario1767754
fuente
5

a, b, c, d, a1, b1, c1 y d1 son referencias a objetos en la memoria, que se identifican de manera única por sus identificadores.

Una operación de asignación toma una referencia al objeto en la memoria y asigna esa referencia a un nuevo nombre. c=[1,2,3,4]es una asignación que crea un nuevo objeto de lista que contiene esos cuatro enteros y asigna la referencia a ese objeto c. c1=ces una asignación que toma la misma referencia al mismo objeto y se la asigna a c1. Dado que la lista es mutable, cualquier cosa que le suceda a esa lista será visible independientemente de si accede a ella co c1porque ambos hacen referencia al mismo objeto.

c1=copy.copy(c)es una "copia superficial" que crea una nueva lista y asigna la referencia a la nueva lista c1. cTodavía apunta a la lista original. Por lo tanto, si modifica la lista en c1, la lista a la que se crefiere no cambiará.

El concepto de copia es irrelevante para objetos inmutables como enteros y cadenas. Como no puede modificar esos objetos, nunca es necesario tener dos copias del mismo valor en la memoria en diferentes ubicaciones. Por lo tanto, los enteros y las cadenas, y algunos otros objetos a los que no se aplica el concepto de copia, simplemente se reasignan. Es por eso que sus ejemplos con ay bresultan en identificaciones idénticas

c1=copy.deepcopy(c)es una "copia profunda", pero en este ejemplo funciona igual que una copia superficial. Las copias profundas difieren de las copias superficiales en que las copias superficiales harán una nueva copia del objeto en sí, pero las referencias dentro de ese objeto no se copiarán. En su ejemplo, su lista solo tiene enteros dentro (que son inmutables) y, como se discutió anteriormente, no es necesario copiarlos. Por lo tanto, la parte "profunda" de la copia profunda no se aplica. Sin embargo, considere esta lista más compleja:

e = [[1, 2],[4, 5, 6],[7, 8, 9]]

Esta es una lista que contiene otras listas (también podría describirla como una matriz bidimensional).

Si ejecuta una "copia superficial" e, copiándola e1, encontrará que la identificación de la lista cambia, pero cada copia de la lista contiene referencias a las mismas tres listas: las listas con números enteros dentro. Eso significa que si tuvieras que hacer e[0].append(3), entonces esería [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Pero e1también lo sería [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Por otro lado, si posteriormente lo hicieras e.append([10, 11, 12]), esería [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. Pero e1aún lo sería [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Esto se debe a que las listas externas son objetos separados que inicialmente contienen tres referencias a tres listas internas. Si modifica las listas internas, puede ver esos cambios sin importar si los está viendo a través de una copia u otra. Pero si modifica una de las listas externas como se indicó anteriormente, entoncesecontiene tres referencias a las tres listas originales más una referencia más a una nueva lista. Y e1todavía solo contiene las tres referencias originales.

Una 'copia profunda' no solo duplicaría la lista externa, sino que también iría dentro de las listas y duplicaría las listas internas, de modo que los dos objetos resultantes no contengan ninguna de las mismas referencias (en lo que respecta a los objetos mutables) . Si las listas internas tuvieran más listas (u otros objetos como diccionarios) dentro de ellas, también se duplicarían. Esa es la parte 'profunda' de la 'copia profunda'.

Andrew Gorcester
fuente
2

En python, cuando asignamos objetos como list, tuples, dict, etc. a otro objeto, generalmente con un signo '=', python crea copias por referencia . Es decir, digamos que tenemos una lista de listas como esta:

list1 = [ [ 'a' , 'b' , 'c' ] , [ 'd' , 'e' , 'f' ]  ]

y asignamos otra lista a esta lista como:

list2 = list1

entonces si imprimimos list2 en la terminal de Python obtendremos esto:

list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]

Tanto list1 como list2 apuntan a la misma ubicación de memoria, cualquier cambio en cualquiera de ellas dará como resultado cambios visibles en ambos objetos, es decir, ambos objetos apuntan a la misma ubicación de memoria. Si cambiamos list1 así:

list1[0][0] = 'x’
list1.append( [ 'g'] )

entonces tanto list1 como list2 serán:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g'] ]
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g’ ] ]

Ahora llegando a la copia superficial , cuando dos objetos se copian mediante una copia superficial, el objeto secundario de ambos objetos primarios se refiere a la misma ubicación de memoria, pero cualquier cambio nuevo en cualquiera de los objetos copiados será independiente entre sí. Comprendamos esto con un pequeño ejemplo. Supongamos que tenemos este pequeño fragmento de código:

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]      # assigning a list
list2 = copy.copy(list1)       # shallow copy is done using copy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

aviso, list2 no se ve afectado, pero si hacemos cambios en objetos secundarios como:

list1[0][0] = 'x’

entonces la lista1 y la lista2 obtendrán cambios:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] ]

Ahora, la copia profunda ayuda a crear objetos completamente aislados entre sí. Si se copian dos objetos a través de Deep Copy, tanto el padre como el hijo apuntarán a una ubicación de memoria diferente. Ejemplo:

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]         # assigning a list
list2 = deepcopy.copy(list1)       # deep copy is done using deepcopy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

aviso, list2 no se ve afectado, pero si hacemos cambios en objetos secundarios como:

list1[0][0] = 'x’

entonces list2 no se verá afectado ya que todos los objetos secundarios y principales apuntan a una ubicación de memoria diferente:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f  ' ] ]

Espero eso ayude.

Nitish Chauhan
fuente
0

El siguiente código muestra la diferencia entre la asignación, copia superficial utilizando el método de copia, copia superficial utilizando el (corte) [:] y la copia profunda. El siguiente ejemplo utiliza listas anidadas al hacer las diferencias más evidentes.

from copy import deepcopy

########"List assignment (does not create a copy) ############
l1 = [1,2,3, [4,5,6], [7,8,9]]
l1_assigned = l1

print(l1)
print(l1_assigned)

print(id(l1), id(l1_assigned))
print(id(l1[3]), id(l1_assigned[3]))
print(id(l1[3][0]), id(l1_assigned[3][0]))

l1[3][0] = 100
l1.pop(4)
l1.remove(1)


print(l1)
print(l1_assigned)
print("###################################")

########"List copy using copy method (shallow copy)############

l2 = [1,2,3, [4,5,6], [7,8,9]]
l2_copy = l2.copy()

print(l2)
print(l2_copy)

print(id(l2), id(l2_copy))
print(id(l2[3]), id(l2_copy[3]))
print(id(l2[3][0]), id(l2_copy[3][0]))
l2[3][0] = 100
l2.pop(4)
l2.remove(1)


print(l2)
print(l2_copy)

print("###################################")

########"List copy using slice (shallow copy)############

l3 = [1,2,3, [4,5,6], [7,8,9]]
l3_slice = l3[:]

print(l3)
print(l3_slice)

print(id(l3), id(l3_slice))
print(id(l3[3]), id(l3_slice[3]))
print(id(l3[3][0]), id(l3_slice[3][0]))

l3[3][0] = 100
l3.pop(4)
l3.remove(1)


print(l3)
print(l3_slice)

print("###################################")

########"List copy using deepcopy ############

l4 = [1,2,3, [4,5,6], [7,8,9]]
l4_deep = deepcopy(l4)

print(l4)
print(l4_deep)

print(id(l4), id(l4_deep))
print(id(l4[3]), id(l4_deep[3]))
print(id(l4[3][0]), id(l4_deep[3][0]))

l4[3][0] = 100
l4.pop(4)
l4.remove(1)

print(l4)
print(l4_deep)
print("##########################")
print(l4[2], id(l4[2]))
print(l4_deep[3], id(l4_deep[3]))

print(l4[2][0], id(l4[2][0]))
print(l4_deep[3][0], id(l4_deep[3][0]))
Sandeep
fuente
0

El GIST a tomar es el siguiente: tratar con listas poco profundas (sin sublistas, solo elementos individuales) usando "asignación normal" aumenta un "efecto secundario" cuando crea una lista superficial y luego crea una copia de esta lista usando "asignación normal" . Este "efecto secundario" se produce cuando cambia cualquier elemento de la lista de copias creado, porque cambiará automáticamente los mismos elementos de la lista original. Eso es copyútil, ya que no cambiará los elementos de la lista original al cambiar los elementos de copia.

Por otro lado, también copytiene un "efecto secundario", cuando tiene una lista que contiene listas (sub_lists) y la deepcopyresuelve. Por ejemplo, si crea una lista grande que tiene listas anidadas (sub_lists) y crea una copia de esta lista grande (la lista original). El "efecto secundario" surgiría cuando modifique las sub_listas de la lista de copias, lo que modificaría automáticamente las sub_listas de la lista grande. A veces (en algunos proyectos) desea mantener la lista grande (su lista original) tal como está sin modificaciones, y todo lo que desea es hacer una copia de sus elementos (sub_lists). Para eso, su solución es usar el deepcopyque se encargará de este "efecto secundario" y hará una copia sin modificar el contenido original.

Los diferentes comportamientos copyy deep copyoperaciones se refieren solo a objetos compuestos (es decir, objetos que contienen otros objetos como listas).

Estas son las diferencias ilustradas en este ejemplo de código simple:

primero

Vamos a ver cómo se copycomporta (superficial), creando una lista original y una copia de esta lista:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

Ahora, ejecutemos algunas printpruebas y veamos cómo se comporta la lista original en comparación con su lista de copias:

original_list y copy_list tienen diferentes direcciones

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

Los elementos de original_list y copy_list tienen las mismas direcciones

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

Los subelementos de original_list y copy_list tienen las mismas direcciones

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08

la modificación de elementos original_list NO modifica elementos copy_list

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

modificar elementos copy_list NO modifica elementos original_list

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

modificar sub_elementos original_list modificar automáticamente sub_elementos copy_list

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]

modificando copy_list sub_elements modifica automáticamente original_list sub_elements

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]

Segundo

Vamos a ver cómo se deepcopycomporta, haciendo lo mismo que hicimos con nosotros copy(creando una lista original y una copia de esta lista):

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

Ahora, ejecutemos algunas printpruebas y veamos cómo se comporta la lista original en comparación con su lista de copias:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)

original_list y copy_list tienen diferentes direcciones

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

Los elementos de original_list y copy_list tienen las mismas direcciones

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

Los subelementos de original_list y copy_list tienen diferentes direcciones

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300

la modificación de elementos original_list NO modifica elementos copy_list

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

modificar elementos copy_list NO modifica elementos original_list

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

modificar sub_elementos original_list NO modifica sub_elementos copy_list

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

modificando copy_list sub_elements NO modifica original_list sub_elements

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]
Fouad Boukredine
fuente
0

No estoy seguro de si se mencionó anteriormente o no, pero es muy importante entender que .copy () crea una referencia al objeto original. Si cambia el objeto copiado, cambia el objeto original. .deepcopy () crea un nuevo objeto y hace una copia real del objeto original en uno nuevo. Cambiar un nuevo objeto copiado en profundidad no afecta al objeto original.

Y sí, .deepcopy () copia el objeto original de forma recursiva, mientras que .copy () crea un objeto de referencia a los datos de primer nivel del objeto original.

Por lo tanto, la diferencia de copia / referencia entre .copy () y .deepcopy () es significativa.

remort
fuente
0

La copia profunda está relacionada con estructuras anidadas. Si tiene una lista de listas, entonces la copia profunda también copia las listas anidadas, por lo que es una copia recursiva. Con solo copiar, tiene una nueva lista externa, pero las listas internas son referencias. La asignación no se copia. Para ex

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.copy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

Salida

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Método de copia copia el contenido de la lista externa a la nueva lista pero la lista interna es sigue siendo igual para ambas listas, por lo que si realiza cambios en la lista interna de cualquier lista, afectará a ambas.

Pero si usa la copia profunda, también creará una nueva instancia para la lista interna.

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.deepcopy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

Salida

[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]

Shubham Agarwal
fuente
-1
>>lst=[1,2,3,4,5]

>>a=lst

>>b=lst[:]

>>> b
[1, 2, 3, 4, 5]

>>> a
[1, 2, 3, 4, 5]

>>> lst is b
False

>>> lst is a
True

>>> id(lst)
46263192

>>> id(a)
46263192 ------>  See here id of a and id of lst is same so its called deep copy and even boolean answer is true

>>> id(b)
46263512 ------>  See here id of b and id of lst is not same so its called shallow copy and even boolean answer is false although output looks same.
sudhir tataraju
fuente
ano es una copia profunda de lst!
Georgy