Python3 中浅拷贝 与 深拷贝 理解
我的gitee链接:
00.Python/Chapter03.DataContainers.md · wan230114/PythonNote - 码云 - 开源中国
https://gitee.com/wan230114/PythonNote/blob/master/00.Python/Chapter03.DataContainers.md
(浅层复制 与 深层复制 理解)
浅拷贝 shallow copy
深拷贝 deep copy
总结:
浅拷贝: 是指在复制过程中,只复制一层变量绑定关系,不会复制深层变量绑定的对象的复制过程
深拷贝: 对所有可变对象进行层层复制,实现对象的各自独立。
3.6.3.1. 语法及使用方法:
基本语法:
import copy # 导入copy模块
L = "任意类型数据"
L2 = copy.copy(L) # 浅拷贝
L2 = copy.deepcopy(L) # 深拷贝
特别的,在列表中还可以通过切片和自身的copy方法进行浅层复制,如下:
# 浅拷贝
# 1) 利用切片方法。切片——返回切片后的新对象。如
L2 = L[:]
L2 = L[::]
# 2) 利用列表自身方法
L2 = L.copy()
3.6.3.2. 原理理解
图解:
- 创建L列表
创建3个数据对象1, (2, 3), [4, 5]
,并将其绑定于数据容器对应位置
L[0] L[1] L[2] # 索引(变量)绑定关系
| | |
L = [-10, (-20, -30), [-40, -50, (-60, -70)]]
- 对L浅拷贝绑定X
最外层可变数据容器重新在内存中另一区域开辟创建, 而内一层所有数据对象, 只是复制了之前的“数据对象”与“变量”的引用绑定关系到当前数据容器,
因而改变最外层新拷贝对象对原始对象无影响,而改变拷贝后的数据对象如X[2],将会使L[2]也同时发生改变
如下图:
L[0] L[1] L[2]
| | |
L = [-10, (-20, -30), [-40, -50, (-60, -70)]]
| | | | | | # 2)内部所有对象正常赋值绑定
[ ] # 1)重新创建最外层可变数据容器
X = [ ] # 绑定原始对象关系
X[0] X[1] X[2]
- 对L深拷贝绑定Y
可以简单理解为所有的数据对象全部在内存中拷贝一份,重新指定绑定关系。
因而,深拷贝后的数据无论如何操作都将不会影响到之前的数据对象,即改变拷贝后的数据对象如Y[2],不会影响L[2]同时发生改变
(不过深拷贝的实际情况为了节省计算机资源,只是复制和重新绑定了新的可变数据对象,而其中不可变的数据对象依然保留,重新赋值绑定,这样节省内存资源的同时亦达到了完全拷贝的同样效果。)
L[0] L[1] L[2]
| | |
L = [-10, (-20, -30), [-40, -50, (-60, -70)]]
| | | | | | | # 2)其余不可变对象正常赋值绑定
[ [ ]] # 1)重新创建所有可变数据容器
Y = [ [ ]] # 绑定新对象关系
Y[0] Y[1] Y[2]
注:不论嵌套多少层可变对象,它们最终都会重新复制创建
示例:(验证)
import copy
# 1) L列表的创建
L = [-10, (-20, -30), [-40, (-60, -70)]]
Lid = [id(L[0]), id(L[1]), id(L[1][0]), id(L[1][0]), id(L[2][0]), id(L[2][1])]
# 2) 浅拷贝
X = L[:]
Xid = [id(X[0]), id(X[1]), id(X[1][0]), id(X[1][0]), id(X[2][0]), id(X[2][1])]
# 4种浅拷贝方式,效果等价
# X = L[:]
# X = L[::]
# X = L.copy()
# X = copy.copy(L)
# 3) 深拷贝
Y = copy.deepcopy(L)
Yid = [id(Y[0]), id(Y[1]), id(Y[1][0]), id(Y[1][0]), id(Y[2][0]), id(Y[2][1])]
# 对于不可变数据对象的id
print("不可变对象的id", Lid)
print("不可变对象的id", Xid)
print("不可变对象的id", Yid)
# 对于可变数据对象的id
print('原 始', id(L[2]))
print('浅拷贝', id(X[2]))
print('深拷贝', id(Y[2]))
# 改变可变对象
print("L", L)
L[2].append(None)
print('L', L)
print('X', X) # 绑定的数据对象也被改变
print('Y', Y) # 可变数据对象已被复制,无影响
"""
不可变对象的id [1785103083024, 1785102803400, 1785074796720, 1785074796720, 1785074796592, 1785105149896]
不可变对象的id [1785103083024, 1785102803400, 1785074796720, 1785074796720, 1785074796592, 1785105149896]
不可变对象的id [1785103083024, 1785102803400, 1785074796720, 1785074796720, 1785074796592, 1785105149896]
原 始 1785105256008
浅拷贝 1785105256008
深拷贝 1785105345224
L [-10, (-20, -30), [-40, (-60, -70)]]
L [-10, (-20, -30), [-40, (-60, -70), None]]
X [-10, (-20, -30), [-40, (-60, -70), None]]
Y [-10, (-20, -30), [-40, (-60, -70)]]
"""
练习1:
import copy # 导入复制模块
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = copy.deepcopy(L1) # 实现深拷贝
L[0] = 3.14
print(L1) # _________
print(L2) # _________
# [1, 2, [3.14, 3.2]] #此列表由于浅拷贝受影响
# [1, 2, [3.1, 3.2]] #此列表不受影响
练习2:
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
a.append(5)
a[4].append('c')
print(a) # _________
print(b) # _________
print(c) # _________
print(d) # _________
# [1, 2, 3, 4, ['a', 'b', 'c'], 5]
# [1, 2, 3, 4, ['a', 'b', 'c'], 5]
# [1, 2, 3, 4, ['a', 'b', 'c']]
# [1, 2, 3, 4, ['a', 'b']]
"""解析:
> a: a加了5,a[4]加了'c'
> b: 赋值绑定操作,与a完全一致
> c: 浅拷贝了最外层可变对象,最外层不受影响,但内部可变对象受影响
> d: 深拷贝,所有可变对象不受影响"""