官网链接: https://docs.python.org/zh-cn/3.9/library/copy.html
官网对深拷贝浅拷贝的解释:
浅层与深层复制的区别仅与复合对象(即包含列表或类的实例等其他对象的对象)相关:
-
浅层复制 构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的 引用 插入其中。
-
深层复制 构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的 副本 插入其中。
深度复制操作通常存在两个问题, 而浅层复制操作并不存在这些问题:
-
递归对象 (直接或间接包含对自身引用的复合对象) 可能会导致递归循环。
-
由于深层复制会复制所有内容,因此可能会过多复制(例如本应该在副本之间共享的数据)。
导入相关模块
import copy
展开讲讲
-
浅层与深层复制的区别仅与
复合对象(即包含列表或类的实例等其他对象的对象)相关
, 深拷贝、浅拷贝会构造一个新的复合对象
什么是复合对象?官网也讲到了,嵌套的对象,比如列表,类的实例等
非复合对象:
初始化一下变量obj = 1 copy1 = copy.copy(obj) copy2 = copy.deepcopy(obj)
输出看一下
print(id(obj)) print(id(copy1)) print(id(copy2)) print(obj) print(copy1) print(copy2)
输出结果
1483367213360 1483367213360 1483367213360 1 1 1
由此可以看出对
整数
1 进行深拷贝、浅拷贝是没有效果的,三个内存地址全部相同
复合对象
初始化一下变量obj = [1] copy1 = copy.copy(obj) copy2 = copy.deepcopy(obj)
输出看一下
print(id(obj)) print(id(copy1)) print(id(copy2)) print(obj) print(copy1) print(copy2)
输出结果
2782767232384 2782769860992 2782769854336 [1] [1] [1]
根据输出结果我们可以发现对
列表
进行深拷贝、浅拷贝是有效果的,内存地址是不同的,正印证了这一句话深拷贝、浅拷贝会构造一个新的复合对象
-
浅层复制 构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的
引用
插入其中。
深层复制 构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的副本
插入其中。
从官网的解释中不难看出,浅拷贝
生成新的复合对象,是将原始对象中找到的对象引用
插入其中,
在原始对象中找到的对象也可以称为子对象
,而引用
就是直接引用原子对象
的内存地址
,这种情况下,如果原对象中的子对象
发生变化
浅拷贝生成的对象也会发生变化。
深拷贝
则是将子对象的副本
插入其中,不是直接引用内存地址
, 所以原子对象发生变化,深拷贝的子对象也不会变。
原对象发生变化
初始化一下变量obj = [1, 2, [1, 2, [3]]] copy1 = copy.copy(obj) copy2 = copy.deepcopy(obj)
输出看一下
print(id(obj)) print(id(copy1)) print(id(copy2)) print(obj) print(copy1) print(copy2) obj.append(9) print(id(obj)) print(id(copy1)) print(id(copy2)) print(obj) print(copy1) print(copy2)
输出结果
1961225041536 1961222432768 1961225042240 [1, 2, [1, 2, [3]]] [1, 2, [1, 2, [3]]] [1, 2, [1, 2, [3]]] 1961225041536 1961222432768 1961225042240 [1, 2, [1, 2, [3]], 9] [1, 2, [1, 2, [3]]] [1, 2, [1, 2, [3]]]
原对象发生变化,深拷贝、浅拷贝的对象没有随之变化
原对象中的子对象发生变化
初始化一下变量obj = [1, 2, [1, 2, [3]]] copy1 = copy.copy(obj) copy2 = copy.deepcopy(obj)
输出看一下
print(id(obj)) print(id(copy1)) print(id(copy2)) print(obj) print(copy1) print(copy2) obj[2].append(8) obj[2][2].append(7) print(id(obj)) print(id(copy1)) print(id(copy2)) print(obj) print(copy1) print(copy2)
输出结果
2713593263872 2713591707776 2713593264576 [1, 2, [1, 2, [3]]] [1, 2, [1, 2, [3]]] [1, 2, [1, 2, [3]]] 2713593263872 2713591707776 2713593264576 [1, 2, [1, 2, [3, 7], 8]] [1, 2, [1, 2, [3, 7], 8]] [1, 2, [1, 2, [3]]]
可以看出,原对象内的子对象变化后,浅拷贝的随之变化,深拷贝却没有变化
-
深度复制操作通常存在两个问题
深拷贝操作时多注意以上两个问题
实验代码
其实二维列表就够用了,多一层也没什么意义
import copy
obj = [1, 2, [1, 2, [3]]]
copy1 = copy.copy(obj)
copy2 = copy.deepcopy(obj)
print(id(obj))
print(id(copy1))
print(id(copy2))
print(obj)
print(copy1)
print(copy2)
obj.append(9)
obj[2].append(8)
obj[2][2].append(7)
print(id(obj))
print(id(copy1))
print(id(copy2))
print(obj)
print(copy1)
print(copy2)