一、前言
Python的数据类型:
- 不可变数据类型:数值类型(int、float)、字符串、元组
- 可变数据类型:列表、字典、集合
深浅copy的模块(copy):
- copy.copy() 浅拷贝
- copy.deepcopy() 深拷贝
二、不可变数据类型的深浅拷贝
2.1 浅拷贝
1 #!/usr/bin/env python 2 # -*-coding:utf-8-*- 3 4 """ 5 @author:fyh 6 @time:2019/6/5 7 """ 8 import copy 9 10 a = 123 11 b = copy.copy(a) 12 print(b) 13 print(id(a)) 14 print(id(b)) 15 16 # 输出结果 17 # 123 18 # 1891531600 19 # 1891531600 20 21 s1 = "abc" 22 s2 = copy.copy(s1) 23 print(s2) 24 print(id(s1)) 25 print(id(s2)) 26 27 # 输出结果 28 # abc 29 # 2586689354584 30 # 2586689354584
通过上面的示例可以看出:不可变类型进行浅拷贝不会给拷贝的对象开辟新的内存空间,而只是拷贝了这个对象的引用。
2.2 深拷贝
1 #!/usr/bin/env python 2 # -*-coding:utf-8-*- 3 4 """ 5 @author:fyh 6 @time:2019/6/5 7 """ 8 import copy 9 10 a = 123 11 b = copy.deepcopy(a) 12 print(b) 13 print(id(a)) 14 print(id(b)) 15 16 # 输出结果 17 # 123 18 # 1891531600 19 # 1891531600 20 21 s1 = "abc" 22 s2 = copy.deepcopy(s1) 23 print(s2) 24 print(id(s1)) 25 print(id(s2)) 26 27 # 输出结果 28 # abc 29 # 2586689354584 30 # 2586689354584
通过上面的示例可以看出:不可变类型进行深拷贝不会给拷贝的对象开辟新的内存空间,也是拷贝了这个对象的引用。
原理如下图:
三、可变类型的深浅拷贝
3.1 浅拷贝
1 #!/usr/bin/env python3 2 3 """ 4 @author:fyh 5 """ 6 import copy 7 8 9 my_list1 = ['苹果', '鸭梨'] 10 my_list2 = copy.copy(my_list1) 11 print("my_list1:", id(my_list1), "my_list2:", id(my_list2)) 12 my_list1[0] = '香蕉' 13 print(my_list1, my_list2) 14 15 # 结果 16 # my_list1: 140246877880712 my_list2: 140246877802120 17 # ['香蕉', '鸭梨'] ['苹果', '鸭梨'] 18 19 # 结论:对可变类型可以进行浅拷贝,会对对象开辟新的内存空间 20 21 my_list3 = ['苹果', '鸭梨', ['橘子', '橙子']] 22 my_list4 = copy.copy(my_list3) 23 print("my_list3:", id(my_list3), "my_list4:", id(my_list4)) 24 # 结果 my_list3: 140703644308360 my_list4: 140703644310728 25 26 print("my_list3[2]:", id(my_list3[2]), "my_list4[2]:", id(my_list4[2])) 27 # 结果:my_list3[2]: 140309865347272 my_list4[2]: 140309865347272 28 29 my_list3[2][0] = '凤凰' 30 print("my_list3", my_list3, "my_list4", my_list4) 31 # 结果:my_list3 ['苹果', '鸭梨', ['凤凰', '橙子']] my_list4 ['苹果', '鸭梨', ['凤凰', '橙子']] 32 33 my_list3[0] = "aa" 34 35 print("my_list3", my_list3, "my_list4", my_list4) 36 # 结果:my_list3 ['aa', '鸭梨', ['凤凰', '橙子']] my_list4 ['苹果', '鸭梨', ['凤凰', '橙子']] 37 38 # 结论:浅拷贝只会对对象的第一层对象进行拷贝
结论:copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象。
原理如下图:
未修改前:
修改后的:
3.2 深拷贝
1 #!/usr/bin/env python3 2 3 """ 4 @author:fyh 5 """ 6 import copy 7 8 list1 = [1, 2] 9 list2 = copy.deepcopy(list1) 10 print("list1", id(list1), "list2", id(list2)) 11 # 结果:list1 140200541024008 list2 140200540991112 12 13 list1[0] = 3 14 print(list1, list2) 15 # 结果:[3, 2] [1, 2] 16 17 list3 = [3, 4, [5, 6]] 18 list4 = copy.deepcopy(list3) 19 print("list3", id(list3), "list4", id(list4)) 20 # 结果:list3 140370543248904 list4 140370543250184 21 print("list3[2]", id(list3[2]), "list4[2]", id(list4[2])) 22 # print("list3", id(list3), "list4", id(list4)) 23 list3[2][0] = 7 24 print(list3, list4) 25 # 结果:[3, 4, [7, 6]] [3, 4, [5, 6]]
结论:可变类型进行深拷贝会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。
原理如下图:
四、总结
- 浅拷贝使用copy.copy函数
- 深拷贝使用copy.deepcopy函数
- 不管是给对象进行深拷贝还是浅拷贝,只要拷贝成功就会开辟新的内存空间存储拷贝的对象。
- 浅拷贝和深拷贝的区别是:
- 浅拷贝最多拷贝对象的一层,深拷贝可能拷贝对象的多层。