a = [11, 22] b = a print(id(a)) print(id(b)) a.append(33) print(a) print(b)
结果(id一致)
1157228286408 1157228286408 [11, 22, 33] [11, 22, 33]
import copy a = [11, 22] c = copy.deepcopy(a) print(id(a)) print(id(c)) a.append(33) print(a) print(c)
结果(id不一致,a增加以后,c不增加)
2312887095752 2312887096264 [11, 22, 33] [11, 22]
c深拷贝a,c指向了另一个地址,该地址将a指向的列表完全拷贝了一份,此时a和c没有任何关系,当a指向的列表append后,c指向的列表不会append。
浅拷贝是对于一个对象的顶层拷贝。通俗的理解是:拷贝了引用,并没有拷贝内容
运用copy模块进行演示
import copy a = [11, 22] b = [33, 44] c = [a, b] e = copy.copy(c) print(id(c)) print(id(e)) print(id(c[0])) print(id(e[0])) a.append(55) print(c) print(e)
结果
2323393015432 2323373459848 2323343954376 2323343954376 [[11, 22, 55], [33, 44]] [[11, 22, 55], [33, 44]]
e = copy.copy(c)
e只拷贝c,而其中c中指向的数据不会改变。
使得e指向一个新的地址来拷贝c,但其中的数据依然指向a和b,当a增加时,e也会增加。
那么d=c
与d = copy.copy(c)有什么不同呢?
a = [11, 22] b = [33, 44] c = [a, b] d = c print(id(c)) print(id(d)) a.append(55) c.append([66,77]) print(c) print(d)
结果
1999078026952 1999078026952 [[11, 22, 55], [33, 44], [66, 77]] [[11, 22, 55], [33, 44], [66, 77]]
import copy a = [11, 22] b = [33, 44] c = [a, b] d = copy.copy(c) print(id(c)) print(id(d)) a.append(55) c.append([66,77]) print(c) print(d)
结果
2794624642760 2794576124296 [[11, 22, 55], [33, 44], [66, 77]] [[11, 22, 55], [33, 44]]
-
d=c
-
d=copy.copy(c)
深拷贝
深拷贝是对于一个对象所有层次的拷贝(递归)
import copy a = [11, 22] b = [33, 44] c = [a, b] d = copy.deepcopy(c) print(id(c)) print(id(d)) print(id(c[0])) print(id(d[0])) a.append(55) print(c) print(d)
结果
1806966386312 1806917863752 1806917298248 1806966385096 [[11, 22, 55], [33, 44]] [[11, 22], [33, 44]]
拷贝对象为不可变量的情况
现在我们拷贝的对象都是可变的(列表),那么拷贝不可变量(元组)会发生什么情况呢?需要我来探讨下。
拷贝元组
import copy a = (11, 22) b = copy.copy(a) print(id(a)) print(id(b))
结果
1778596640456 1778596640456
注意:copy.copy()
如果拷贝元组,不会进行拷贝,仅仅是指向。
原因:元组是不可遍历型,无法进行数据的修改,因此copy.copy()
会进行判断,如果copy元组变成指向。
copy.deepcopy()深拷贝
同理,大家可以自己试一试。
如果元组中存着变量为可变类型呢?又会发生什么呢?
import copy a = [11,22] b = [33,44] c = (a,b) e = copy.copy(c) d = copy.deepcopy(c) print(id(c)) print(id(e)) print(id(d)) a.append(55) print(c) print(e) print(d)
结果
1885947170760 1885947170760 1885947222856 ([11, 22, 55], [33, 44]) ([11, 22, 55], [33, 44]) ([11, 22], [33, 44])
从结果可以看出,浅拷贝依然为指向,指向了c,相当于e = c
,当a或b发生变化时,e也发生了变化;
而深拷贝指向了新的地址,并拷贝了一份新的a和b,与之前c中的a和b列表不同,当a或b发生变化时,d不会发生了变化。
总结
-
-
如果拷贝的是一个拥有可变类型的数据时,即使时元组是最顶层(元组中含有可变数据),那么
copy.deepcopy()
依然是深拷贝,copy.copy()
a = [11, 22] b = [33, 44] c = [a, b] d = c[:] print(c) print(d) print(id(c)) print(id(d)) print(id(c[0])) print(id(d[0])) a.append(55) print(c) print(d)
结果
[[11, 22], [33, 44]] [[11, 22], [33, 44]] 2105046387272 2105027365256 2105026105800 2105026105800 [[11, 22, 55], [33, 44]] [[11, 22, 55], [33, 44]]
可以看出,d指向新的地址,但其中的数据仍然指向a和b,所以列表的切片任然是浅拷贝。
d = dict(name="charles", age=27,num=[11,22]) co = d.copy() print(d) print(co) print(id(d)) print(id(co)) print(id(d['name'])) print(id(co['name'])) d["num"].append(9) print(d) print(co) d["sex"] = "M" print(d) print(co)
结果
{'name': 'charles', 'age': 27, 'num': [11, 22]} {'name': 'charles', 'age': 27, 'num': [11, 22]} 1697702296936 1697704568136 1697702278704 1697702278704 {'name': 'charles', 'age': 27, 'num': [11, 22, 9]} {'name': 'charles', 'age': 27, 'num': [11, 22, 9]} {'name': 'charles', 'age': 27, 'num': [11, 22, 9], 'sex': 'M'} {'name': 'charles', 'age': 27, 'num': [11, 22, 9]}
字典中,键指向存放值的地址。
def test_nums(temp): temp.append(33) nums = [11, 22] test_nums(nums) print(nums)
结果
[11, 22, 33]
import copy def test_nums(temp): temp.append(33) print("列表temp:%s"%temp) nums = [11, 22] test_nums(copy.deepcopy(nums)) print("列表nums:%s" %nums)
结果
列表temp:[11, 22, 33] 列表nums:[11, 22]
将深拷贝的参数传递给函数后,函数的操作不会对nums列表有任何影响。
以上就是深拷贝与浅拷贝的一些总结了,如果您有什么疑问,请留言,欢迎大家一起讨论。
来源:https://www.cnblogs.com/The-Chao/p/12425338.html