python生成矩阵,使用[[0]*n]*m,我们会发现,当改变其中某一个元素时,整列数据都会发生改变,而使用[[0 for i in range(n)] for j in range(m)]才可以生成正常的矩阵。
这是因为,list是可变元素,而int是不可变元素,对于list存储采用指针,引用型变量,改变矩阵其中某一个元素值,导致所有行的这个位置的元素都会改变。下面具体分析:
1、python列表的存储形式
Python列表和C语言数组不同,并不是存的实在的值,而是存放的只想其他实例的指针。所以也就能够理解 为什么python列表里里面什么东西都可以放进去而不需要考虑类型了~
2、 [0] * 2的存储形式
这里的 0 是同一个实例,可以通过以下代码发现这点~
(id表示查看实例的唯一标识符~)
3、 [[0]*2]*2的存储形式
下面两个箭头代表着下面的两行其实就是指向第一行两个指针,所以这里更改任意一行,都会对其他行产生影响,如图:
这里明明只更改了第三行的第三个元素,但是所有行的第三个元素都发生了变化,所以这也说明了指针这一特性,[[0]2]2所产生的其他行都 只是简单的指向第一行,不是进行复制 **,所以更改任意一行,其他行都会产生变化!
4、 [[0 for i in range(3)] for j in range(3)]
虽然里面所有的0 都是一个实例,但是进行修改时,修改的是不同的列表,如图:
(这里的lst就是用上面的 [[0]*3]*3来产生的,而another是由列表解析式产生的),可以看出,lst每一行的id都是一样的,而another是不一样的,即代表着不同的行,修改其中一行并不会对另外的行产生影响。
也有小伙伴会问了,那列表解析式里面每个元素都是同一个,修改其中一个难道不会对其他有影响吗,这里我贴出一下代码,朋友们可以自行测试一下。
aa = [0 for i in range(3)] # 不可变类型
for i in aa: print(id(i))
aa = [[0] for i in range(3)] # 可变类型
for i in aa: print(id(i))
aa = ['1' for i in range(3)] # 不可变类型
for i in aa: print(id(i))
aa = [(1,2) for i in range(3)] # 不可变类型
for i in aa: print(id(i))
不可变类型修改的时候是创建一个全新的实例,如果每个id都不一样的话,会非常耗费内存,而且一般不会对其他东西有影响,所以就创建相同的实例,但是可变类型不能这样,可变类型如果id相同,那么修改他们的元素会对其他实例产生影响,所以每个实例都应该是一个全新的实例
归根结底,还是我这里第一条所概述的,Python的列表存储方式是用的指针指向实例地址来存储的,列表里面放的就是指针的地址。文章来源:https://www.toymoban.com/news/detail-416426.html
所以,君不见python里面没有指针,但是指针始终如影随形。😁文章来源地址https://www.toymoban.com/news/detail-416426.html
到了这里,关于python生成矩阵为何[[0 for i in range(n)] for j in range(m)]而不能[[0]*n]*m的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!