python自定义长度数组为什么这么自作主张?
a = [[],[],[]]
b = [[]] * 3
a[1].append(5)
b[1].append(5)
print(a)
print(b)
#输出
[[],[5],[]]
[[5],[5],[5]]
为什么用 []乘以常数 的方式自定义长度数组会出现这样的问题?
难道这种方式定义的数组里的所有元素共用一个指针或者是互相引用?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如图,
*
的作用是相当于复制,b中的元素都指向的是同一个地址。这是从图中可以看出的,但是,我也希望找到相关文档可以参考一下原理。a 的赋值相当于:
a1 = []
a2 = []
a3 = []
a = [a1, a2, a3]
b 的赋值相当于:
b1 = []
b = [b1,b1,b1]
是得,所有元素都是由
b[0]
复制而来,它们和b[0]
是同一个对象可以用
b = [[] for _ in range(3)]
类似于浅拷贝,
[[]] * 3
列表里面的对象只是多了一次引用而已,指向的同一个对象,如下:这个涉及到 mutable(可改)与 immutable(不可改) 的问题。
python 对象中除了字符串,数字,元组为 immutable 以外,其他均为 mutable。
对于 mutable(可改的) 的对象在复制时,实际上复制其指针(引用)。并没有重新创建一个对象。
而 imutable(不可改) 的对象在复制时,才会重新创建一个新的值。
这段代码实际上对同一个 [] 空列表对象复制了三次。
b[1].append(5) 虽然只改变了元素1,而元素2,元素0 是和元素1是相同的元素。
Python 一切皆对象,而任何对象都具有 ID(值的地址), 类型, 值 这三个属性:
对于
c = [[]]
,c 内相当于只生成了一个对象,也即c[0]
,因此c[0]
只会有一个值([None])的 ID.对于
d = [[], []]
,d 内相当于生成了两个对象d[0], d[1]
,至于两个对象值是否相等,对于列表这样的可变对象 python 解释器都不会去管,而会一视同仁的分别分配一个值 ID 给同值对象,因此d
内的两个对象其实分别有一个值的ID.对于
b = [[]]*3
这样的操作,*
号只管一字不差的复制 b 内元素b[0]
,而非b[0][0]
,并生成两个新对象b[1]、b[2]
,至于要不要给b[1]、b[2]
开辟等同于b[0][0]
值的ID,*
号根本不管;因为那是b[0]
的属性,而不是b
的。因此,b = [[]]*3
虽然复制出三个独立的b
内对象b[0]\b[1]\b[2]
,但后两个对象的值的引用其实都是照抄b[0]
的,因此完全指向同一个值 ID.(相当于浅复制)。再回到你的问题: