Python - Copiar una lista de listas en Python

 
Vista:

Copiar una lista de listas en Python

Publicado por Titotatin (4 intervenciones) el 07/01/2013 15:30:02
Hola a tod@s. Me ha surgido un problema en uno de mis programillas y me trae de cabeza porque me parece una chorrada, pero no he encontrado la forma de arreglarlo. Antes que nada quiero aclarar que no soy novato en python (llevo unos 5 años haciendo "chapucillas" y programas de cálculo), a pesar de que mi pregunta es bastante básica.

La cuestión es: ¿como copio una lista de listas en python?
Con copiar me refiero exactamente a eso, no a crear otra variable que apunte a la misma lista, sino una nueva. De forma que posteriormente pueda modificar las listas dentro de la lista copiada sin que la original se vea alterada.

Aquí tengo un ejemplo simplificado de lo que trato de hacer, y el problema que se me presenta:

1
2
3
4
5
6
7
8
9
10
>>> l1 = [[0, 0], [0, 0]]
>>> l2 = l1[:]
>>> l1 is l2
False
>>> l2[0][0] = 3  # Modifico el primer elemento de la primera lista de 'l2'
>>> l2
[[3, 0], [0, 0]]
>>> l1
[[3, 0], [0, 0]]
>>> # Ambas listas se ven modificadas.


Creo que entiendo por qué me sucede, pero no se como evitarlo. ¿Alguien me podría iluminar?

Gracias de antemano.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de xve
Val: 2.239
Plata
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Copiar una lista de listas en Python

Publicado por xve (1646 intervenciones) el 07/01/2013 21:16:21
Hola amigo, la verdad es que he probado tus códigos, y me he quedado sorprendido, ya que las direcciones de memoria son diferentes, no se porque razón se modifican las dos...

He probado exactamente lo mismo que tu, mostrando el id de cada lista, y realmente es diferente.
1
2
3
4
5
6
7
8
9
10
11
12
13
l1 = [[0, 0], [1, 0]]
l2 = l1[:]
 
print id(l1)
print id(l2)
 
print l1
print l2
 
l2[0][0] = 3
 
print l1
print l2


Voy a ver si averiguo el porque y te comento...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Copiar una lista de listas en Python

Publicado por Titotatin (4 intervenciones) el 07/01/2013 22:09:49
Gracias por contestar xve.

Sobre el por qué pasa, tengo una ligera idea. Creo que al crear la lista l1 Python realmente crea dos listas ([0, 0] i [1, 0]), y luego crea una tercera cuyos elementos son las direcciones a estas dos. Creo que al copiar l1 a l2 lo único que se duplica son esas direcciones (guardándolas en una nueva lista), no el contenido en si. No se si me explico.

Lo único que se me ocurre por ahora es copiar elemento a elemento la lista de listas con un par de bucles, pero lo veo bastante ineficiente (y poco "elegante", aunque esto no me molesta mucho), sobre todo si la lista es muy larga y a su vez contiene listas largas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de xve
Val: 2.239
Plata
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Copiar una lista de listas en Python

Publicado por xve (1646 intervenciones) el 08/01/2013 07:09:37
He descubierto algo mas... si la lista es una "lista simple", si que funciona correctamente de la manera que indicas:
1
2
3
4
5
6
7
8
9
10
11
12
13
l1 = [1, 0]
l2 = l1[:]
 
print id(l1)
print id(l2)
 
print l1
print l2
 
l2[0] = 3
 
print l1
print l2


Si la lista es una lista de listas, te funcionara con la función deepcopy de la clase copy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import copy
 
l1 = [[0, 0], [1, 0]]
l2 = copy.deepcopy(l1)
 
print id(l1)
print id(l2)
 
print l1
print l2
 
l2[0][0] = 3
 
print l1
print l2


Voy a ver si averiguo el porque y te comento.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Copiar una lista de listas en Python

Publicado por Titotatin (4 intervenciones) el 08/01/2013 11:58:24
No conocía la función deepcopy, aunque desde luego funciona. Pero después de echarle un vistazo a su código, creo que para tan solo copiar listas de listas (vaya, matrices) me es mas eficiente hacer un copiado "a lo bestia":

1
2
3
4
5
6
7
l1 = [[0, 0], [1, 0]]
l2 = [i[:] for i in l1]
 
l2[0][0] = 999
 
print l1
print l2


Que te parece?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de xve
Val: 2.239
Plata
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Copiar una lista de listas en Python

Publicado por xve (1646 intervenciones) el 08/01/2013 14:36:32
La verdad, es que también esta bien... no te sabría decir que es mas eficiente... entiendo que si las matrices son pequeñas, no tienes que tener ningún problema... faltaría ver con una matriz muy grande... aunque si se utiliza una matriz muy extensa, seguramente se tendría que optimizar el código para no utilizar matrices muy extensas...;)

Tu código lo veo perfecto!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Copiar una lista de listas en Python

Publicado por Titotatin (4 intervenciones) el 08/01/2013 15:45:28
En ese caso me quedaré con esa última forma, y me guardo el deepcopy que seguro que me servirá.

Muchas grácias por la ayuda!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Copiar una lista de listas en Python

Publicado por tomas (1 intervención) el 14/10/2016 21:40:26
me paso lo mismo y el problema es que estas copiando de la misma forma, prueba lo siguiente

a = [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
Duplicamos:
>>> b = [x[:] for x in a] <------ esto crea una lista nueva con los mismos datos, pero no la copia indirectamente
>>> b
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> a
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]

Modificamos:
>>> b[0][1]= 7
>>> b
[[0, 7, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> a
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]

Espero que te sea de ayuda

de parte de Eduard Diaz
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar