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

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

在不使用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] * column_len] * row_len 
		for 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]),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)

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

  • 11
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值