There are many ways to declare a 2 dimensional array with given number of rows and columns. Let us look at some of them and also at the small but tricky catches that accompany it.
We can do it using list comprehension, concatenation feature of * operator and few other ways.
Method 0: 2 list comprehensions
Python3
rows = 3 cols = 2 mat = [[ 0 for _ in range (cols)] for _ in range (rows)] print (f 'matrix of dimension {rows} x {cols} is {mat}' ) # editing the individual elements mat[ 0 ][ 0 ], mat[ 0 ][ 1 ] = 1 , 2 mat[ 1 ][ 0 ], mat[ 1 ][ 1 ] = 3 , 4 mat[ 2 ][ 0 ], mat[ 2 ][ 1 ] = 5 , 6 print (f 'modified matrix is {mat}' ) # checking the memory address of first element of a row print (f 'addr(mat[0][0]) = {id(mat[0][0])}, addr(mat[0][1]) = {id(mat[0][1])}' ) print (f 'addr(mat[1][0]) = {id(mat[1][0])}, addr(mat[1][1]) = {id(mat[1][1])}' ) print (f 'addr(mat[2][0]) = {id(mat[2][0])}, addr(mat[2][1]) = {id(mat[2][1])}' ) |
matrix of dimension 3 x 2 is [[0, 0], [0, 0], [0, 0]] modified matrix is [[1, 2], [3, 4], [5, 6]] addr(mat[0][0]) = 11094304, addr(mat[0][1]) = 11094336 addr(mat[1][0]) = 11094368, addr(mat[1][1]) = 11094400 addr(mat[2][0]) = 11094432, addr(mat[2][1]) = 11094464
Method 1: 1 list comprehension inside and 1 concatenation operation outside
Python3
rows = 3 cols = 2 mat = [[ 0 for _ in range (cols)]] * rows print (f 'matrix with dimension {rows} x {cols} is {mat}' ) # editing the individual elements mat[ 0 ][ 0 ], mat[ 0 ][ 1 ] = 1 , 2 mat[ 1 ][ 0 ], mat[ 1 ][ 1 ] = 3 , 4 mat[ 2 ][ 0 ], mat[ 2 ][ 1 ] = 5 , 6 print (f 'modified matrix is {mat}' ) # checking the memory address of first element of a row print (f 'addr(mat[0][0]) = {id(mat[0][0])}, addr(mat[0][1]) = {id(mat[0][1])}' ) print (f 'addr(mat[1][0]) = {id(mat[1][0])}, addr(mat[1][1]) = {id(mat[1][1])}' ) print (f 'addr(mat[2][0]) = {id(mat[2][0])}, addr(mat[2][1]) = {id(mat[2][1])}' ) |
matrix with dimension 3 x 2 is [[0, 0], [0, 0], [0, 0]] modified matrix is [[5, 6], [5, 6], [5, 6]] addr(mat[0][0]) = 11094432, addr(mat[0][1]) = 11094464 addr(mat[1][0]) = 11094432, addr(mat[1][1]) = 11094464 addr(mat[2][0]) = 11094432, addr(mat[2][1]) = 11094464
Method 2: 1 list comprehension outside and 1 concatenation operation inside
Python3
rows = 3 cols = 2 mat = [[ 0 ] * cols for _ in range (rows)] print (f 'matrix with dimension {rows} x {cols} is {mat}' ) # editing the individual elements mat[ 0 ][ 0 ], mat[ 0 ][ 1 ] = 1 , 2 mat[ 1 ][ 0 ], mat[ 1 ][ 1 ] = 3 , 4 mat[ 2 ][ 0 ], mat[ 2 ][ 1 ] = 5 , 6 print (f 'modified matrix is {mat}' ) # checking the memory address of first element of a row print (f 'addr(mat[0][0]) = {id(mat[0][0])}, addr(mat[0][1]) = {id(mat[0][1])}' ) print (f 'addr(mat[1][0]) = {id(mat[1][0])}, addr(mat[1][1]) = {id(mat[1][1])}' ) print (f 'addr(mat[2][0]) = {id(mat[2][0])}, addr(mat[2][1]) = {id(mat[2][1])}' ) |
matrix with dimension 3 x 2 is [[0, 0], [0, 0], [0, 0]] modified matrix is [[1, 2], [3, 4], [5, 6]] addr(mat[0][0]) = 11094304, addr(mat[0][1]) = 11094336 addr(mat[1][0]) = 11094368, addr(mat[1][1]) = 11094400 addr(mat[2][0]) = 11094432, addr(mat[2][1]) = 11094464
Method 3: 2 concatenation operations
Python3
rows = 3 cols = 2 mat = [[ 0 ] * cols] * rows print (f 'matrix with dimension {rows} x {cols} is {mat}' ) # editing the individual elements mat[ 0 ][ 0 ], mat[ 0 ][ 1 ] = 1 , 2 mat[ 1 ][ 0 ], mat[ 1 ][ 1 ] = 3 , 4 mat[ 2 ][ 0 ], mat[ 2 ][ 1 ] = 5 , 6 print (f 'modified matrix is {mat}' ) # checking the memory address of first element of a row print (f 'addr(mat[0][0]) = {id(mat[0][0])}, addr(mat[0][1]) = {id(mat[0][1])}' ) print (f 'addr(mat[1][0]) = {id(mat[1][0])}, addr(mat[1][1]) = {id(mat[1][1])}' ) print (f 'addr(mat[2][0]) = {id(mat[2][0])}, addr(mat[2][1]) = {id(mat[2][1])}' ) |
matrix with dimension 3 x 2 is [[0, 0], [0, 0], [0, 0]] modified matrix is [[5, 6], [5, 6], [5, 6]] addr(mat[0][0]) = 11094432, addr(mat[0][1]) = 11094464 addr(mat[1][0]) = 11094432, addr(mat[1][1]) = 11094464 addr(mat[2][0]) = 11094432, addr(mat[2][1]) = 11094464
Here we can see that output of Method 1 & Method 3 are *unexpected*.
We expected all rows in mat to be all different after we assigned them with 1,2,3,4,5,6 respectively. But in Method1 & Method3 they are all equal to [5,6]. This shows that essentially mat[0],mat[1] & mat[2] are all referencing the same memory which can further be seen by checking their addresses using the id function in python.
Hence be very careful while using (*) operator.
To understand it further we can use 3 dimensional arrays to and there we will have 2^3 possibilities of arranging list comprehension and concatenation operator. This is an exercise I leave for the reader to perform.
If working with numpy then we can do it using reshape method.
Python3
import numpy as np rows = 3 cols = 2 size = rows * cols mat = np.array([ 0 ] * size).reshape(rows,cols) |