1. 浅拷贝和深拷贝的区别
浅拷贝(copy):仅拷贝对象,但不拷贝此对象内的子对象。
深拷贝(deepcopy):完全拷贝对象,包括其内部的子对象。
2. 举例理解
1 2 3 4 5 6 7 8 9 10 11 12 13
|
import copy
a = {0:1, 1:[1,2]}
a1 = copy.copy(a) a2 = copy.deepcopy(a)
a[1].append(3) print(a, '%x' % id(a), '%x' % id(a[1])) print(a1, '%x' % id(a1), '%x' % id(a1[1])) print(a2, '%x' % id(a2), '%x' % id(a2[1]))
|
1 2 3 4
| 输出结果: {0: 1, 1: [1, 2, 3]} 220a8caf2d0 220aa969e08 {0: 1, 1: [1, 2, 3]} 220a8caf318 220aa969e08 {0: 1, 1: [1, 2]} 220aa937c18 220aa969ec8
|
从输出结果进行分析:
1.a、a1、a2三者的id值不同。说明不论深浅拷贝都能得到新的对象。
2.a1[1]和a[1]的id值相同,a2[1]和a[1]的id值不同。说明浅拷贝不能拷贝子对象,执行浅拷贝得到的对象a1的子对象和原对象a的子对象使用的是相同的一块内存,但是执行深拷贝得到的对象a2却和原对象a完全独立。这也是为什么当a[1].append(3)后,a1[1]也跟着变了,而a2[1]却没变。
3. a.copy()和copy.copy(a)的区别
虽然两者都是浅拷贝,但是copy.copy()能够拷贝的对象更多,即某些对象本身是没有copy属性的,比如元组(tuple)。
如果将上例中的a值替换为a = (1, [1,2]),那么执行a1 = a.copy()时是会报错的:
1 2 3 4
|
a = (1, [1,2]) a1 = a.copy()
|
1
| AttributeError: 'tuple' object has no attribute 'copy'
|
4. 引申: 手写字典深拷贝
1 2 3 4 5 6 7 8 9
| def deep_copy(x): '''仅适用于子对象是字典的情况''' x1 = {} for k, v in x.items(): if isinstance(v, dict): x1[k] = deep_copy(v) else: x1[k] = v return x1
|
如果子对象是数组或者元组的话,只要在赋值前价格数据类型判断,然后根据不同的类型赋值给不同的变量即可兼容。