¿Cómo inicializar una matriz bidimensional en Python?
Estoy comenzando con Python y estoy tratando de usar una lista bidimensional, que inicialmente lleno con la misma variable en todos los lugares. Se me ocurrió esto:
def initialize_twodlist(foo):
twod_list = []
new = []
for i in range (0, 10):
for j in range (0, 10):
new.append(foo)
twod_list.append(new)
new = []
Da el resultado deseado, pero parece una solución alternativa. ¿Existe una forma más fácil/corta/elegante de hacer esto?
Para inicializar una lista bidimensional en Python, use
t = [ [0]*3 for i in range(3)]
¡Pero no lo uses [[v]*n]*n
, es una trampa!
>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
Un patrón que aparecía a menudo en Python era
bar = []
for item in some_iterable:
bar.append(SOME EXPRESSION)
lo que ayudó a motivar la introducción de listas por comprensión, que convierten ese fragmento en
bar = [SOME_EXPRESSION for item in some_iterable]
que es más breve y a veces más claro. Por lo general, se adquiere el hábito de reconocerlos y, a menudo, reemplazar los bucles con comprensiones.
Tu código sigue este patrón dos veces
twod_list = [] \
for i in range (0, 10): \
new = [] \ can be replaced } this too
for j in range (0, 10): } with a list /
new.append(foo) / comprehension /
twod_list.append(new) /
Puedes usar una lista por comprensión :
x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of 'foo' (which can depend on i and j if you want)
De esta manera es más rápido que las listas por comprensión anidadas.
[x[:] for x in [[foo] * 10] * 10] # for immutable foo!
Aquí hay algunos tiempos de Python3, para listas pequeñas y grandes.
$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]'
1000000 loops, best of 3: 1.55 usec per loop
$ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]'
100000 loops, best of 3: 6.44 usec per loop
$ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]'
100 loops, best of 3: 5.5 msec per loop
$ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]'
10 loops, best of 3: 27 msec per loop
Explicación:
[[foo]*10]*10
crea una lista del mismo objeto repetido 10 veces. ¡No puedes simplemente usar esto, porque modificar un elemento modificará ese mismo elemento en cada fila!
x[:]
es equivalente a list(X)
pero es un poco más eficiente ya que evita la búsqueda de nombres. De cualquier manera, crea una copia superficial de cada fila, por lo que ahora todos los elementos son independientes.
Sin embargo, todos los elementos son el mismo foo
objeto, por lo que si foo
es mutable , no puedes usar este esquema, tendrías que usar
import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]
o asumiendo una clase (o función) Foo
que devuelve foo
s
[[Foo() for x in range(10)] for y in range(10)]
Para inicializar una matriz bidimensional en Python:
a = [[0 for x in range(columns)] for y in range(rows)]