Multiplicación de listas de Python: [[[]] * 3 hace 3 listas que se reflejan entre sí cuando se modifican [duplicar]


Esta pregunta ya tiene una respuesta aquí:

¿Por qué está sucediendo esto? Realmente no entiendo:

>>> P = [ [()]*3 ]*3
>>> P
[[(), (), ()], [(), (), ()], [(), (), ()]]
>>> P[0][0]=1
>>> P
[[1, (), ()], [1, (), ()], [1, (), ()]]
Author: ninjagecko, 2011-07-14

4 answers

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)]
 22
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-14 03:40:19

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

P = [ [()]*3 for i in range(3) ]
 6
Author: icktoofay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-14 03:40:02

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

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 todavía apunta a la misma lista subyacente.

 5
Author: dhg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-14 03:38:53

También puedes 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 usar el rango. Desde ipython shell:

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
 5
Author: John La Rooy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-14 04:05:34