#原创,转载请先留言联系
在阅读此文前,建议先看一下我的另一篇博文:https://www.cnblogs.com/chichung/p/9607226.html
浅拷贝
import copy copy.copy(obj)
深拷贝
import copy copy.deepcopy(obj)
- 深拷贝与浅拷贝的区别
1.浅拷贝
import copy a = [1,2] b = [3,4] c = [a,b] d = copy.copy(c) print('c的内存地址',id(c)) print('d的内存地址',id(d)) print(' c[0]的内存地址',id(c[0])) print('d[0]的内存地址',id(d[0])) print('a的内存地址',id(a)) 输出: c的内存地址 139752474494984 d的内存地址 139752475133128 c[0]的内存地址 139752474562824 d[0]的内存地址 139752474562824 a的内存地址 139752474562824
由输出结果可知。d列表浅拷贝了c列表,所以d列表重新分配了一个内存空间。但是,由于是浅拷贝,d列表的内部,a列表与b列表并没有进行拷贝,也就没有分配新的内存空间,还是原来的内存空间地址。所以说,浅拷贝是对象的最外层的拷贝。
2.深拷贝
import copy a = [1,2] b = [3,4] c = [a,b] d = copy.deepcopy(c) print('c的内存地址',id(c)) print('d的内存地址',id(d)) print(' c[0]的内存地址',id(c[0])) print('d[0]的内存地址',id(d[0])) print('a的内存地址',id(a)) 输出: c的内存地址 139657913055240 d的内存地址 139657913118792 c[0]的内存地址 139657913118984 d[0]的内存地址 139657913118920 a的内存地址 139657913118984
由输出结果可知。d列表深拷贝了c列表,所以d列表重新分配了一个内存空间。但是,由于是深拷贝,d列表的内部,a列表与b列表也进行了拷贝,也重新分配了内存空间。所以说,深拷贝是拷贝是对象的所有层的拷贝。
上面针对的是可变类型数据的深浅拷贝,不可变类型的深浅拷贝又是不一样的。
附:
不可变类型(不可变类型不能对其内容直接修改,修改的话其实是将新的数据储存到新的内存中):数字、字符串、元组、不可变集合
可变类型(可变类型可以对其内容直接修改,修改的话也是将新的数据储存到原来的内存中):列表、字典、可变集合
- 不可变类型的深浅拷贝(元组,字符串,数字)
import copy a = (1,2) b = copy.copy(a) c = copy.deepcopy(a) print('a的内存空间为',id(a)) print('浅拷贝b的内存空间为',id(b)) print('深拷贝c的内存空间为',id(c)) 输出: a的内存空间为 140239461449608 浅拷贝b的内存空间为 140239461449608 深拷贝c的内存空间为 140239461449608
由输出结果可知。a的元组,b对a进行了浅拷贝,但是内存空间还是没有改变!c对a进行了深拷贝,内存空间还是没有变!可知,对于不可变类型,浅拷贝与深拷贝都是相同的 ,都不会单独开辟内存空间,而是引用原来的内存空间。
- 可变类型与不可变类型嵌套的深浅拷贝
import copy b = [1,2] a= (b, ) copy_a = copy.copy(a) deepcopy_a = copy.deepcopy(a) print('a的内存空间为',id(a)) print('浅拷贝后copy_a的内存空间为',id(copy_a)) print('深拷贝后deepcopy_a的内存空间为',id(deepcopy_a)) print(' a[0]的内存空间为',id(a[0])) print('浅拷贝后copy_a[0]的内存空间为',id(copy_a[0])) print('深拷贝后deepcopy_a[0]的内存空间为',id(deepcopy_a[0])) 输出: a的内存空间为 140588590524736 浅拷贝后copy_a的内存空间为 140588590524736 深拷贝后deepcopy_a的内存空间为 140588560914976 a[0]的内存空间为 140588560399496 浅拷贝后copy_a[0]的内存空间为 140588560399496 深拷贝后deepcopy_a[0]的内存空间为 140588560398408
要拷贝的是a,a是元组里面嵌套一个字典,a=([1,2],)
当进行浅拷贝时,只拷贝最外层,因为最外层是元组,是不可变类型,所以只是引用原来的内存空间,内存与a相同。
当进行深拷贝是,先拷贝最外层,因为最外层是元组,是不可变类型,只是引用原来的内存空间。但是当他开始拷贝第二层时,发现是个可变类型,然后就分配一个新的空间,因此,深拷贝后deepcopy_a[0]的内存空间和a[0]的内存空间不一样。但是问题来了,为什么深拷贝后deepcopy_a的内存空间和a的内存空间不一样?图解!
明白了吧?如果是嵌套可变类型和不可变类型的,实质上深拷贝还是把全部层都拷贝了一遍,全部层都分配了新的内存空间。
还有嵌套全是不可变类型的,那深浅拷贝都是引用原来的内存地址,并不会拷贝。
还有嵌套全是可变类型的,那浅拷贝就会给最外层分配新的内存地址,其它层内存地址不变。深拷贝就会给拷贝所有层,给所有层分配新的内存地址。
相信你搞得懂上面的示例,这两个肯定都懂的。这里就不演示了。
- 列表切片、字典中的copy都采用的是浅拷贝
1.列表切片
import copy a = [[1,2],[3,4]] b = a[:] print('a的内存空间',id(a)) print('b的内存空间',id(b)) print(' a[0]的内存空间',id(a[0])) print('b[0]的内存空间',id(b[0])) 输出: a的内存空间 140020984498184 # 最外层拷贝了,因为内存空间重新分配了 b的内存空间 140020984565832 a[0]的内存空间 140020984566024 # 里面的层没有拷贝,还是原来的内存空间 b[0]的内存空间 140020984566024
import copy a = {'name':['chichung','cong'],'age':22} b = a.copy() print('字典a的内存地址:',id(a)) print('字典b的内存地址:',id(b)) print(' 字典a里name的内存地址:',id(a['name'])) print('字典b里name的内存地址:',id(b['name'])) 输出: 字典a的内存地址: 139921205047240 # 最外层拷贝了,因为内存空间重新分配了 字典b的内存地址: 139921205006472 字典a里name的内存地址: 139921174875464 # 里面的层没有拷贝,还是原来的内存空间 字典b里name的内存地址: 139921174875464
因此,列表切片、字典中的copy都采用的是浅拷贝。
最后的tips:python中内存数据的拷贝默认是浅拷贝。