copy和deepcopy
python中copy是浅拷贝,deepcopy是深拷贝,那么两者有啥区别呢?
浅拷贝copy字面意思是一层拷贝,即指拷贝对象本身,不拷贝对象中的子对象,举个例子,就是列表的列表,
浅拷贝只能拷贝外层列表对象,列表中的列表子对象没有被拷贝。但是新生成的拷贝对象id(地址)是和原对象id
是不同的,也就是说浅拷贝也重新申请了一块新内存。
深拷贝deepcopy就是真正意义的拷贝,就是把原对象重新复制一遍作为一个新对象,新申请一块内存。
两者区别就在于浅拷贝的子对象还和原对象对应位置共用一块内存空间(即id相同,是同一块内存对象的引用),
而深拷贝完完全全重新生成了一个和原对象相同的新的个体,新的内存空间。
对于不可变类型(元组、字符串、数值)的浅拷贝,拷贝前后对象id值相同,使用浅拷贝和深拷贝基本一样,对于
可变类型(列表、字典),尽量使用深拷贝,如果使用浅拷贝,注意原子对象修改会影响浅拷贝的值。
接下来看例子说明:
1. 赋值、浅拷贝、深拷贝(对象尽可能不复杂,选用可变类型对象)
# 可变对象,对象尽可能不复杂a = [1, 2, 3, 5] b = a c = copy(a) d = deepcopy(b)print(id(a), id(b), id(c), id(d))print("a: ", a)print("b: ", b)print("c: ", c)print("d: ", d) a.append(4)print("a: ", a)print("b: ", b)print("c: ", c)print("d: ", d)# 打印结果2057448665992 2057448665992 2057448611464 2057448140424a: [1, 2, 3, 5] b: [1, 2, 3, 5] c: [1, 2, 3, 5] d: [1, 2, 3, 5] a: [1, 2, 3, 5, 4] b: [1, 2, 3, 5, 4] c: [1, 2, 3, 5] d: [1, 2, 3, 5]
从上面结果可以看出,对于不复杂的对象,浅拷贝和深拷贝都会申请新内存,且改变原对象不会影响到新拷贝的对象。
2. 赋值、浅拷贝、深拷贝(对象复杂,列表中套列表)
# 可变对象,对象复杂a = [1, 2, 3, 5, [2, 2]] b = a c = copy(a) d = deepcopy(b)print(id(a), id(b), id(c), id(d))print("a: ", a)print("b: ", b)print("c: ", c)print("d: ", d) a[-1].append(4)print("a: ", a)print("b: ", b)print("c: ", c)print("d: ", d) 打印结果1599110209288 1599110209288 1599110407944 1599110408008a: [1, 2, 3, 5, [2, 2]] b: [1, 2, 3, 5, [2, 2]] c: [1, 2, 3, 5, [2, 2]] d: [1, 2, 3, 5, [2, 2]] a: [1, 2, 3, 5, [2, 2, 4]] b: [1, 2, 3, 5, [2, 2, 4]] c: [1, 2, 3, 5, [2, 2, 4]] d: [1, 2, 3, 5, [2, 2]]
注意到对于复杂的对象来说,浅拷贝没有拷贝子对象,因此修改原对象中子对象值,浅拷贝的对象也发生改变。
3. 赋值、浅拷贝、深拷贝(不可变类型对象)
# 不可变对象a = "copy test"b = a c = copy(a) d = deepcopy(b)print(id(a), id(b), id(c), id(d))print("a: ", a)print("b: ", b)print("c: ", c)print("d: ", d 打印结果 1273137289328 1273137289328 1273137289328 1273137289328a: copy test b: copy test c: copy test d: copy test
对于不可变类型,深拷贝和浅拷贝前后对象id是一样,即是同一块内存对象的引用。