Python multi-dimensional lists
This section illustrates how multi-dimension array functionality can be used in Python
without working with NumPy. This would only be recommended for simple linear algebra
tasks where efficiency is not important. Python defines multi-dimensional arrays using
collections of collections of collections etc. Here the collection may be a Python list or, if
the associated data does not need modifying, a tuple. In particular, matrices can be
implemented using collections of collections. For example, we could define a 2×3 matrix
using a list of lists:
x = [[1,2,3],[4,5,6]]
The elements are accessed in the normal Python way:
y = x[1][2] # Value in row 1 column 2 (y equals 6)
x[0][1] = 7 # Value in row 0 column 1 set to 7
# x becomes [[1,7,3],[4,5,6]]
The rows of a matrix can be accessed easily:
row = x[0] # Gives [1,2,3]
and the columns slightly less easily:
col = [y[2] for y in x] # Gives [3,6]
Note that len(x) gives the number of rows and len(x[0]) (or any element) gives the
number of columns of the matrix, assuming the matrix is not empty:
len(x) # 2
len(x[0]) # 3
Strictly speaking, for any function that manipulates a matrix, it should be checked that
we actually have a matrix, and in particular that it has a consistent number of entries in
each row. In the interest of brevity, here we leave out most checks. Without such caution,
if someone tried to use nonsense data it would raise an exception,
6
but the error message
might not make it clear what the problem is.
Standard Python does not provide any inbuilt functionality for matrix (or higher multi-
dimensional array) manipulation, so it all has to be implemented by the programmer. As
an example we illustrate a function that creates the transpose of a matrix. The transpose of
a matrix is a new matrix with the first row of the original matrix becoming the first
column in the new matrix, the second row becoming the second column etc. It is relatively
simple to implement, here using list comprehension:
def transposeMatrix(x):
nrows = len(x)
ncols = len(x[0])
return [[x[n][m] for n in range(nrows)] for m in range(ncols)]
This just goes through all the elements in the transposed order.
x = [[1,7,3], [4,5,6]]
y = transposeMatrix(x) # y = [[1,4],[7,5],[3,6]]
Matrix multiplication is a bit harder:
def multiplyMatrices(x, y):
rowsX = len(x)
colsX = len(x[0])
rowsY = len(y)
colsY = len(y[0])
if colsX != rowsY:
message = 'x is %d x %d; inconsistent with y which is %d x %d'
raise Exception(message % (rowsX, colsX, rowsY, colsY))
z = rowsX * [0] # Constructs a list of zeros, of size rowsX
for i in range(rowsX):
z[i] = colsY * [0]
for j in range(colsX):
for k in range(colsY):
z[i][k] += x[i][j] * y[j][k]
return z
Here it is checked that the number of columns in x is the same as the number of rows in
y, because that is an easy mistake to make when using the function. There is a triple loop
to do the sums, which is why matrix multiplication is slow, at least when it is done this
way.
It might be tempting to initialise z using:
z = rowsX * [colsY*[0]]
but that does not work because it creates a matrix with literally the same list in each row,
so the additions would affect all the rows, not just the given row. So the initialisation is
done in two steps. First a list of the correct length is created:
z = rowsX * [0]
Here it does not matter what is used as the repeated item, because that is immediately
replaced by a list of the correct length in the loop and the summation is done.
for i in range(m):
z[i] = colsY * [0]
If this is as sophisticated as the code is required to get in terms of linear algebra, and
efficiency is not an issue, then it is acceptable to do things this way. However, for anything
more sophisticated, e.g. matrix inversion, it makes most sense to use the NumPy module.
Do'stlaringiz bilan baham: |