首页 > 其他 > 详细

深拷贝与浅拷贝

时间:2018-09-08 19:47:33      阅读:175      评论:0      收藏:0      [点我收藏+]

#原创,转载请先留言联系

在阅读此文前,建议先看一下我的另一篇博文: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(\nc[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(\nc[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(\na[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(\na[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(\n字典a里name的内存地址:,id(a[name]))
print(字典b里name的内存地址:,id(b[name]))

输出:
字典a的内存地址: 139921205047240  # 最外层拷贝了,因为内存空间重新分配了
字典b的内存地址: 139921205006472

字典a里name的内存地址: 139921174875464  # 里面的层没有拷贝,还是原来的内存空间
字典b里name的内存地址: 139921174875464

因此,列表切片、字典中的copy都采用的是浅拷贝。

最后的tips:python中内存数据的拷贝默认是浅拷贝。

 

深拷贝与浅拷贝

原文:https://www.cnblogs.com/chichung/p/9609786.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!