使用python编写矩阵(也被称为多维数组)的一个基本的方法就是使用嵌套的列表结构。例如,如下代码使用嵌套列表的列表定义了3*3的矩阵。
如果使用一次索引,会得到一整行(实际上,也就是嵌套的子列表),如果使用两次索引,你将会得到某一行里的其中一项。
#!/usr/bin/env python
# coding=utf-8
import numpy as np
matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9] ]
print matrix
print matrix[1]
print matrix[1][1]
使用这样的结构,我们总是能够索引行,以及索引行中的列,使用通常的索引操作。
列表解析也是处理这样结构的强大的工具,因为它将会自动为我们扫描行和列。例如,尽管这种结构通过行存储了矩阵,为了选择第二列,我们能够简单地通过对行进行迭代,之后从所需要的列中提取出元素,或者就像下面一样通过在行内的位置进行迭代。
M=[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
print(M)
print(M[1][2])
ret=[row[1] for row in M]
print(ret)
ret=[M[row][1] for row in (0, 1, 2)]
print(ret)
M=[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
ret=[M[i][i] for i in range(len(M))]
print(ret)
M=[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
N=[[2, 2, 2],
[3, 3, 3],
[4, 4, 4]]
ret=[M[row][col] * M[row][col] for row in range(3) for col in range(3) ]
print(ret)
M=[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
N=[[2, 2, 2],
[3, 3, 3],
[4, 4, 4]]
ret=[ [M[row][col] * M[row][col] for col in range(3)] for row in range(3)]
print(ret)
这个表达式时有效的,因为row迭代是外层的循环。对于每个row,它运行嵌套的列的迭代来创建矩阵每一行的结果。它等同于如下的基于语句的代码。
res=[]
for row in range(3):
tmp=[]
for col in range(3):
tmp.append(M[row][col] * M[row][col])
res.append(tmp)
print(ret)
与这些语句相比,列表解析这个版本只需要一行代码,而且可能对于大型矩阵来说,运行相当快。
性能优势:基于对运行在当前python下的测试,map调用要比等效的for循环要快两倍,而列表解析往往比map调用要稍快一些。速度上的差距是来自于底层实现上,map和列表解析是在解释器中以C语言的速度来运行的,比python的for循环代码在PVM中步进运行要快得多。