在学习python时,发现使用append函数想要在list后添加元素,结果却把整个list都覆盖为同一个元素了
问题代码(这里我把代码中的循环去掉了,留下开始两步):
l = [1]
b = []
b.append(l)
print(‘l: ‘,l)
print(‘b: ‘,b)
l.append(2)
b.append(l)
print(‘l: ‘,l)
print(‘b: ‘,b)
预期输出:
l: [1]
b: [[1]]
l: [1, 2]
b: [[1], [1, 2]]
实际输出:
l: [1]
b: [[1]]
l: [1, 2]
b: [[1, 2], [1, 2]]
这是什么原因造成的呢,实际上,append方法是浅拷贝:在python中,对象赋值实际上是对象的引用,当创建一个对象,然后把它赋值给另一个变量的时候,python并没有拷贝这个对象,而是只拷贝了这个对象的引用。
在上面的代码中b.append(l)
就是对l进行了浅拷贝,结果是b=[[1]],但是b[0]与a引用的对象是相同的,可以通过下面的代码验证:
l = [1]
b = []
b.append(l)
print(‘l: ‘,id(l))#id() 函数返回对象的唯一标识符,标识符是一个整数。
print(‘b[0]: ‘,id(b[0]))
执行结果:
l: 2544058841472
b[0]: 2544058841472
说明这两个对象指向的地址是一样的。
上面的代码中我们希望将l改变后在添加到b的后面,可是由于吧b[0]这个变量和l引用同一个对象,所以改变l后,b[0]也改变了,所以最后的结果被覆盖。
为了避免这种情况,我们把l中的内容每次复制到另一个list中,再把这个新的list添加到b末尾:
l = [1]
b = []
#新建一个list
L = l.copy()
b.append(L)
print(‘l: ‘,l)
print(‘b: ‘,b)
l.append(2)
L = l.copy()
b.append(L)
print(‘l: ‘,l)
print(‘b: ‘,b)
这样即可得到预期输出。