¿Por qué .append() afecta a todos los elementos de una lista de listas?
Creo una lista de listas y quiero agregar elementos a las listas individuales, pero cuando intento agregarlos a una de las listas ( a[0].append(2)
), el elemento se agrega a todas las listas.
a = []
b = [1]
a.append(b)
a.append(b)
a[0].append(2)
a[1].append(3)
print(a)
Da:[[1, 2, 3], [1, 2, 3]]
Mientras que yo esperaría:[[1, 2], [1, 3]]
Cambiar la forma en que construyo la lista inicial de listas, haciendo b
un int en lugar de una lista y colocando los corchetes dentro .append()
, me da el resultado deseado:
a = []
b = 1
a.append([b])
a.append([b])
a[0].append(2)
a[1].append(3)
print(a)
Da:[[1, 2], [1, 3]]
¿Pero por qué? No es intuitivo que el resultado deba ser diferente. Sé que esto tiene que ver con que haya múltiples referencias a la misma lista , pero no veo dónde está sucediendo eso.
Es porque la lista contiene referencias a objetos. Tu lista no contiene [[1 2 3] [1 2 3]]
, lo es [<reference to b> <reference to b>]
.
Cuando cambia el objeto (agregando algo a b
), está cambiando el objeto en sí, no la lista que contiene el objeto.
Para obtener el efecto que desea, su lista a
debe contener copias de b
en lugar de referencias a b
. Para copiar una lista puedes usar el rango [:]
. Por ejemplo:
>>> a = []
>>> b = [1]
>>> a.append(b[:])
>>> a.append(b[:])
>>> a[0].append(2)
>>> a[1].append(3)
>>> print a
[[1, 2], [1, 3]]
La clave es esta parte:
a.append(b)
a.append(b)
Está agregando la misma lista dos veces, por lo que ambas a[0]
y a[1]
son referencias a la misma lista.
En su segundo ejemplo, está creando nuevas listas cada vez que llama a append like a.append([b])
, por lo que son objetos separados que se inicializan con el mismo valor flotante.
Para hacer una copia superficial de una lista, el modismo es
a.append(b[:])
que cuando se duplica hará que a tenga dos copias nuevas de la lista b
que no le darán el error de alias que informa.