python创建矩阵不用numpy_python实现矩阵乘法(不用numpy)

python实现矩阵乘法

不使用其他库的情况下实现矩阵乘法

在不使用numpy库的情况下实现矩阵乘法,看起来很简单,但这之中也是存在坑的。比如如下代码:

class mat_mul():

def mm(self,A,B):

row_len = len(A)

column_len = len(B[0])

cross_len = len(B)

res_mat = [[0] * row_len] * column_lenfor i in range(row_len):

for j in range(column_len):

for k in range(cross_len):

temp = A[i][k] * B[k][j]

res_mat[i][j] += temp

print "==="

print res_mat

def main():

A = [[1,1,1],[2,0,2]]

B = [[0,1],[1,0],[1,1]]

m = mat_mul()

m.mm(A,B)

if __name__ == '__main__':

main()

结果本应该是

可是最终程序运行完结果却是

最终将中间结果输出,发现问题出现在矩阵初始化阶段:

res_mat = [[0] * row_len] * column_len

这里我想初始化一个row_len*column_len的全0矩阵,所以[0]*row_len,再将新生成的list乘以coluimn_len。这里问题就出现了:

python中,如果将list 乘以k,表面上看起来是将list复制了k份,然而事实证明这k个list所指向的内存中的对象只有一个,即原始的list,也就是说如果其中一个list被改变,k个list都会跟着变。

举例:

c = [[0]*2]*2

print "before:",c

c[0][1] = 3

print "after:",c

最终输出结果:

可以看到我只给第0行的第一个元素赋值3,这却导致第1行的第一个元素跟着改变。

可以使用python的id函数查看每个列表的在内存内的地址:

print id(c[0])<

244d1

/span>,id(c[1])

39642936 39642936

最终发现其地址是一样的。

所以,正确的初始化方法是:

res_mat = [[0] * row_len for i in range(column_len)]

这样最终的结果就没有问题啦。

原来一直以为了解python,但是对于其底层实现还掌握的太少太少。以后应该多注意这方面的学习。

PS:

列表的复制方法:

lista=[1,[2,3]]

listb=lista[:]

listb=[i for i in lista]

listb=copy.copy(lista)

listb=copy.deepcopy(lista)

只有第五种是完全拷贝,其他在不同场合下都会出现以上问题。

你可能感兴趣的:(python创建矩阵不用numpy_python实现矩阵乘法(不用numpy))