Multiplicación de la lista de Python: ] * 3 hace 3 listas que se duplican entre sí cuando se modifica

¿Por qué sucede esto? Realmente no entiendo:

>>> P = [ [()]*3 ]*3 >>> P [[(), (), ()], [(), (), ()], [(), (), ()]] >>> P[0][0]=1 >>> P [[1, (), ()], [1, (), ()], [1, (), ()]] 

Has hecho 3 referencias a la misma lista.

 >>> a = b = [] >>> a.append(42) >>> b [42] 

Quieres hacer esto:

 P = [[()] * 3 for x in range(3)] 

Las listas son mutables, y multiplicar una lista por un número no copia sus elementos. Puede intentar cambiarlo a una lista de comprensión, por lo que evaluará [()]*3 tres veces, creando tres listas diferentes:

 P = [ [()]*3 for i in range(3) ] 

También puede escribirlo así, lo que tiene la ventaja de mostrar la estructura [[()]*3]*3

 >>> P=[i[:] for i in [[()]*3]*3] >>> P[0][0]=1 >>> P [[1, (), ()], [(), (), ()], [(), (), ()] 

También es un poco más rápido que el uso de rango. Desde el shell de ipython:

 In [1]: timeit P = [ [()]*3 for i in range(3) ] 1000000 loops, best of 3: 1.41 us per loop In [2]: timeit P=[i[:] for i in [[()]*3]*3] 1000000 loops, best of 3: 1.27 us per loop 

En realidad, es la misma lista interna (la misma referencia) que se duplica 3 veces, de modo que cuando modifica cualquiera de ellos, en realidad los está modificando todos.

Entonces, la lista interna [()]*3 produce una lista de tres tuplas. Pero entonces esta lista se duplica tres veces. Sin embargo, en Python, es realmente una lista de referencias que se está multiplicando, por lo que la referencia se duplica, pero cada referencia sigue apuntando a la misma lista subyacente.