Creando listas de listas de forma pythonica.

Estoy usando una lista de listas para almacenar una matriz en Python. Intenté inicializar una matriz cero de 2×3 de la siguiente manera.

mat=[[0]*2]*3 

Sin embargo, cuando cambio el valor de uno de los elementos en la matriz, cambia el valor de esa entrada en cada fila, ya que la identificación de cada fila en el mat es la misma. Por ejemplo, después de asignar

 mat[0][0]=1 

mat es [[1, 0], [1, 0], [1, 0]] .

Sé que puedo crear la matriz Cero usando un bucle de la siguiente manera,

 mat=[[0]*2] for i in range(1,3): mat.append([0]*2) 

¿Pero puede alguien mostrarme una forma más pythonica?

Use una lista de comprensión :

 >>> mat = [[0]*2 for x in xrange(3)] >>> mat[0][0] = 1 >>> mat [[1, 0], [0, 0], [0, 0]] 

O, como una función:

 def matrix(rows, cols): return [[0]*cols for x in xrange(rows)] 

Prueba esto:

 >>> cols = 6 >>> rows = 3 >>> a = [[0]*cols for _ in [0]*rows] >>> a [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]] >>> a[0][3] = 2 >>> a [[0, 0, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]] 

Esto también se discute en esta respuesta :

 >>> lst_2d = [[0] * 3 for i in xrange(3)] >>> lst_2d [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>> lst_2d[0][0] = 5 >>> lst_2d [[5, 0, 0], [0, 0, 0], [0, 0, 0]] 

¡Esta es más rápida que la respuesta aceptada!
Usar xrange (filas) en lugar de [0] * filas no hace ninguna diferencia.

 >>> from itertools import repeat >>> rows,cols = 3,6 >>> a=[x[:] for x in repeat([0]*cols,rows)] 

Una variación que no usa itertools y corre a la misma velocidad.

 >>> a=[x[:] for x in [[0]*cols]*rows] 

Desde ipython:

 In [1]: from itertools import repeat In [2]: rows=cols=10 In [3]: timeit a = [[0]*cols for _ in [0]*rows] 10000 loops, best of 3: 17.8 us per loop In [4]: timeit a=[x[:] for x in repeat([0]*cols,rows)] 100000 loops, best of 3: 12.7 us per loop In [5]: rows=cols=100 In [6]: timeit a = [[0]*cols for _ in [0]*rows] 1000 loops, best of 3: 368 us per loop In [7]: timeit a=[x[:] for x in repeat([0]*cols,rows)] 1000 loops, best of 3: 311 us per loop 

yo suelo

 mat = [[0 for col in range(3)] for row in range(2)] 

aunque dependiendo de lo que haga con la matriz después de crearla, puede echar un vistazo utilizando una matriz NumPy.

Esto funcionara

 col = 2 row = 3 [[0] * col for row in xrange(row)] 

Qué pasa:

 m, n = 2, 3 >>> A = [[0]*m for _ in range(n)] >>> A [[0, 0], [0, 0], [0, 0]] >>> A[0][0] = 1 [[1, 0], [0, 0], [0, 0]] 

Aka Lista de comprensión; de los documentos :

 List comprehensions provide a concise way to create lists without resorting to use of map(), filter() and/or lambda. The resulting list definition tends often to be clearer than lists built using those constructs. 

Si los tamaños involucrados son realmente solo 2 y 3,

 mat = [[0, 0], [0, 0], [0, 0]] 

es fácilmente el mejor y no se ha mencionado todavía.

Consulte también esta pregunta para obtener información general sobre una matriz anidada / lista anidada de n niveles.

¿Hay algo que itertools no pueda hacer? 🙂

 >>> from itertools import repeat,izip >>> rows=3 >>> cols=6 >>> A=map(list,izip(*[repeat(0,rows*cols)]*cols)) >>> A [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]] >>> A[0][3] = 2 >>> A [[0, 0, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]