为什么要用拷贝,直接 = 不香吗?
第一次接触Python列表,就看到Python列表的方法中有一个list.copy() ,用于复制列表,这时候就很奇怪,为什么明明可以直接用list1 = list2 ,还要多次一举用list1 = list2.copy() ?于是我就直接用了 = 创建了一个和原列表一模一样的列表。
list1 = [1, 2, 3, 4, 5]
list2 = list1
print(list2)
以下为运行结果: 也没有什么不好的嘛,直接抛弃list.copy() 方法,不看了(开个玩笑)。之后我打算在list2 中添加数据,这时再看list1 ,问题就出现了,list1 居然也跟着list2 一起发生了变化。
list1 = [1, 2, 3, 4, 5]
list2 = list1
list2.extend([6])
print(list2)
print(list1)
这就说明在这段程序中,list1 和list2 是同样的东西,只不过用了不同的两个名字而已。为了验证这个猜想,我们可以用is 这个照妖镜来看看list1 和list2 到底是不是一个东西。is 也被叫做同一性运算符,这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同。 这就是为什么Python需要给列表这个数据结构一个list.copy() 的原因。
浅拷贝显神通
针对列表直接等于创建新列表出现的问题,浅拷贝就很好地解决了这个问题。但是浅拷贝也并不是万能的,这个我们在下文会提及。
list1 = [1, 2, 3, 4, 5]
list2 = list1.copy()
print(list2 is list1)
list2.extend([6])
print(list1)
print(list2)
以下为运行结果 可以清楚地看到用list.copy() 方法创建的新列表,不会与原来的列表相同,也就是说这时的list1 和list2 就完全分离开来,各自的增删改操作不会影响对方。
你使用= 符号,使得list1 和list2 指向同一个内容,而copy则是将list1 的内容复制后让list2 指向这个拷贝的内容上了。
那么还会有什么问题呢?这不是已经完全解决了吗?那么我们来试试列表嵌套。
list1 = [1, 2, 3, [4, 5]]
list2 = list1.copy()
list2[3][0] = 5
print(list2)
print(list1)
Wow?我们惊奇地发现当列表的元素为列表时,我们的浅拷贝并没有很好地完成任务,原因是其实也很好理解,我们前面说了copy是将list1 的内容复制后让list2 指向这个拷贝的内容上了。而将列表[1,2,3,[4,5]] copy后,list1 中元素[4,5] 被拷贝的只是地址,所以list2 指向的仍是[4,5] 这个本体。
看不明白的朋友可以看看下面这个图,应该就可以看明白~ 所以为了解决这个问题,深拷贝就出现了
究极武器——深拷贝
用深拷贝之前,我们需要引入copy 包。
import copy
list1 = [1, 2, 3, [4, 5]]
list2 = copy.deepcopy(list1)
list2[3][0] = 5
print(list1)
print(list2)
这样就完美解决了问题😁~而且使用深拷贝,不管是几层嵌套,都可以起到拷贝的作用!
为什么不都用深拷贝?
因为效率~,深拷贝的实现效率要低于浅拷贝,所以在浅拷贝就可以实现的程序里还是使用浅拷贝吧~
|