¿Cómo copiar en profundidad una lista?
Después E0_copy = list(E0)
, supongo E0_copy
que es una copia profunda de E0
ya que id(E0)
no es igual a id(E0_copy)
. Luego modifico E0_copy
en el bucle, pero ¿por qué E0
no es lo mismo después?
E0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for k in range(3):
E0_copy = list(E0)
E0_copy[k][k] = 0
#print(E0_copy)
print E0 # -> [[0, 2, 3], [4, 0, 6], [7, 8, 0]]
E0_copy
No es una copia profunda. No haces una copia profunda usando list()
. (Ambos list(...)
y testList[:]
son copias superficiales, así como también testList.copy()
.)
Se utiliza copy.deepcopy(...)
para copiar en profundidad una lista.
copy.deepcopy(x[, memo])
Devuelve una copia profunda de x .
Vea el siguiente fragmento:
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]
Ahora mira la deepcopy
operación .
>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]
Para explicarlo, list(...)
no hace copias recursivas de los objetos internos. Solo hace una copia de la lista más externa, sin dejar de hacer referencia a las mismas listas internas, por lo tanto, cuando muta las listas internas, el cambio se refleja tanto en la lista original como en la copia superficial. Puede ver que la copia superficial hace referencia a las listas internas marcando id(a[0]) == id(b[0])
dónde b = list(a)
.
En Python, hay un módulo llamado copy
con dos funciones útiles:
import copy
copy.copy()
copy.deepcopy()
copy()
es una función de copia superficial. Si el argumento dado es una estructura de datos compuesta, por ejemplo una lista , entonces Python creará otro objeto del mismo tipo (en este caso, una nueva lista ), pero para todo lo que esté dentro de la lista anterior, solo se copia su referencia. Piénselo como:
newList = [elem for elem in oldlist]
Intuitivamente, podríamos suponer que deepcopy()
seguiría el mismo paradigma, y la única diferencia es que para cada elemento llamaremos recursivamente deepcopy (al igual que la respuesta de mbguy )
¡pero esto está mal!
deepcopy()
en realidad conserva la estructura gráfica de los datos compuestos originales:
a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)
# check the result
c[0] is a # False, a new object a_1 is created
c[0] is c[1] # True, c is [a_1, a_1] not [a_1, a_2]
Esta es la parte complicada: durante el proceso de deepcopy()
, se utiliza una tabla hash (diccionario en Python) para asignar cada referencia de objeto antiguo a cada referencia de objeto nueva, lo que evita duplicados innecesarios y, por lo tanto, preserva la estructura de los datos compuestos copiados.
Documentos oficiales
Si el contenido de la lista son tipos de datos primitivos, puede utilizar una comprensión
new_list = [i for i in old_list]
Puedes anidarlo para listas multidimensionales como:
new_grid = [[i for i in row] for row in grid]
@Sukrit Kalra
No.1: list()
, [:]
, copy.copy()
son todas copias superficiales. Si un objeto es compuesto, no todos son adecuados. Necesitas usar copy.deepcopy()
.
No.2: b = a
directamente, a
y b
tienen la misma referencia, cambiar a
es igual que cambiar b
.
establecer a a b
si lo asigna a
directamente b
y a
comparte b
una referencia.
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[1, [4, 5, 6]]
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
instantánea
porlist()
list()
y [:]
son iguales. Excepto los cambios de la primera capa, se transferirán todos los cambios de las demás capas.
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
por[:]
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
list() y [:] cambian las otras capas, excepto la primera capa
# =========== [:] ===========
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2] = 4
>>> a
[[1, 2, 4], [4, 5, 6]]
>>> b
[[1, 2, 4], [4, 5, 6]]
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = a[:]
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2][0] = 999
>>> a
[[1, 2, [999, 6]], [4, 5, 6]]
>>> b
[[1, 2, [999, 6]], [4, 5, 6]]
# =========== list() ===========
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2] = 4
>>> a
[[1, 2, 4], [4, 5, 6]]
>>> b
[[1, 2, 4], [4, 5, 6]]
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>> a[0][2][0] = 999
>>> a
[[1, 2, [999, 6]], [4, 5, 6]]
>>> b
[[1, 2, [999, 6]], [4, 5, 6]]
porcopy()
Encontrará que copy()
la función es la misma que list()
y [:]
. Todos ellos son copias superficiales .
Para obtener mucha más información sobre la copia superficial y la copia profunda, tal vez pueda consultar aquí .
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.copy(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
pordeepcopy()
>>> import copy
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.deepcopy(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0] = 1
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.deepcopy(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
Si los elementos de su lista son objetos inmutables , entonces puede usar esto; de lo contrario, debe usarlo deepcopy
desde copy
el módulo.
También puedes usar la forma más corta para una copia profunda list
como esta.
a = [0,1,2,3,4,5,6,7,8,9,10]
b = a[:] #deep copying the list a and assigning it to b
print id(a)
20983280
print id(b)
12967208
a[2] = 20
print a
[0, 1, 20, 3, 4, 5, 6, 7, 8, 9,10]
print b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10]