a = [[],[],[]]
b = [[]] * 3
a[1].append(5)
b[1].append(5)
print(a)
print(b)
#输出
[[],[5],[]]
[[5],[5],[5]]
为什么用 []乘以常数 的方式自定义长度数组会出现这样的问题?
难道这种方式定义的数组里的所有元素共用一个指针或者是互相引用?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
如图,
*的作用是相当于复制,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.(相当于浅复制)。再回到你的问题: