最近遇到了一个问题,在python中对于对象的复制有两种,copy()以及deepcopy(),为了研究他们之间的区别,写下以下博客。
首先查看python的官方文档,获得以下解释:python
浅层复制和深层复制之间的区别仅与复合对象 (即包含其余对象的对象,如列表或类的实例) 相关: 一个 浅层复制 会构造一个新的复合对象,而后(在可能的范围内)将原对象中找到的 引用 插入其中。 一个 深层复制 会构造一个新的复合对象,而后递归地将原始对象中所找到的对象的 副本 插入。
为了明白其中的原理,作了以下实验:code
简单对象是指不包含子对象的对象,也就是只包含普通元素(数字,字符串)的对象,对于简单对象,copy与deepcopy方法没有什么区别,下面的一段代码,能够先看一下效果是怎样的。对象
import copy if __name__ == '__main__': a = [1, 2, 3, 4] b = copy.copy(a) c = copy.deepcopy(a) print(a == b) print(a is b) print(a == c) print(a is c)
执行上面的代码,咱们能够看到执行结果,深复制和浅复制的执行结果是同样的递归
True # 说明 a 和 b 所指向的对象的内容相同 False # 说明 a 和 b 所指向的不是同一个对象(地址不一样) True # 说明 a 和 c 所指向的对象的内容相同 False # 说明 a 和 c 所指向的不是同一个对象(地址不一样)
能够用一张图来解释一下,为何简单对象的深浅复制是同样的。内存
咱们知道,上面的图中,变量a指向一个List对象(或者说是一个List对象的引用),该对象在内存中占用一个地址空间,当简单对象执行copy和deepcopy中的对象时,咱们能够看到不管时深复制仍是浅复制,都是在内存中新开辟一个地址空间,将原来对象中的内容复制过去,同时让b成为新对象的引用。所以,咱们看到a和b指向的对象是不一致的,可是内容是相同的。文档
复杂对象能够理解为另外包含其余简单对象的对象,也就是包含子对象的对象,例如:List中嵌套List,或者Dict中嵌套List等,对于复杂对象咱们先来看一个简单的程序示例。字符串
import copy if __name__ == '__main__': a = {'name': 'test', 'age': 56, 'address': [1, 2, 3, 4, 5]} b = copy.copy(a) print(a is b) print(a['address'] is b['address']) c = copy.deepcopy(a) print(a is c) print(a['address'] is c['address'])
执行结果以下:博客
False # 说明 a 和 b 不是同一个对象的引用 True # 说明 a中的address 和 b 中的 address 是同一个对象。黑人问号脸?? False # 说明 a 和 c 不是同一个对象的引用 False # 说明 a中的address 和 c 中的 address 不是同一个对象
下面我经过一张图,来大概解释一下为何会出现上面的结果。PS:具体对象的对象不必定是按照图中的方式,为了可以说明原理,本图中将子对象的存储空间单独抽出,方便理解。class
咱们看到对于复杂对象(包含子对象的对象)的复制,深浅复制在实现原理上就有所不一样了。经过上图咱们能够看到,复杂对象的深浅复制的区别在于复杂对象的子对象。能够看到:test