一、前言

在使用python的过程中,我们往往遇到python的拷贝操作。一般来说,python的拷贝分为深度拷贝和浅层拷贝,它们之间有一定的区别,应用场景也不尽相同。接下来让我们来详细看一下这两者之间的异同之处。

二、python深浅拷贝

不可变类型(字符串、数值型、布尔值)的深浅拷贝

# 不可变对象的浅拷贝,以数值为例
1. import copy
2. a=5
3. # 浅拷贝
4. b=copy.copy(a)
5. print(id(a))
6. print(id(b))
7.
8. # 修改 a 的值
9. a=10
10. print(id(a))
11. print(id(b))
12. # 140732266387232
13. # 140732266387232
14. # 140732266387392
15. # 140732266387232
16.
17. # 不可变对象的深拷贝,以数值为例
18. import copy
19. a=5
20. # 深拷贝
21. b=copy.deepcopy(a)
22. print(id(a))
23. print(id(b))
24.
25. # 修改 a 的值
26. a=10
27. print(id(a))
28. print(id(b))
29.
30. # 140732266387232
31. # 140732266387232
32. # 140732266387392
33. # 140732266387232

对于不可变类型(字符串、数值型、布尔值):浅拷贝和深拷贝一样,对象的引用(内存地址)没有发生变化。可变对象(列表、字典、集合)的浅拷贝

1. import copy
2. lsta = [1, 2, 3]
3. lstb = [1, 2, [3, 4, 5]]
4. lsta1 = copy.copy(lsta) # 非嵌套浅拷贝
5. lstb1 = copy.copy(lstb) # 嵌套列表浅拷贝
6. print(id(lsta))
7. print(id(lsta1))
8. print(id(lsta[0]), id(lsta[1]),id(lsta[2]))
9. print(id(lsta1[0]), id(lsta1[1]), id(lsta1[2]))
10. # 1373054849088
11. # 1373054934336
18
12. # 140732266387104 140732266387136 140732266387168
13. # 140732266387104 140732266387136 140732266387168
14. print(id(lstb))
15. print(id(lstb1))
16. print(id(lstb[0]), id(lstb[2]), id(lstb[2][0]))
17. print(id(lstb1[0]), id(lstb1[2]), id(lstb1[2][0]))
18. # 2735667449472
19. # 2735667458368
20. # 140732266387104 2735667382912 140732266387168
21. # 140732266387104 2735667382912 140732266387168

可变对象(列表、字典、集合)的深拷贝

1. import copy
2. lsta = [1, 2, 3]
3. lstb = [1, 2, [3, 4, 5]]
4. lsta1 = copy.deepcopy(lsta) # 非嵌套深拷贝
5. lstb1 = copy.deepcopy(lstb) # 嵌套列表深拷贝
6.
7. print(id(lsta))
8. print(id(lsta1))
9. print(id(lsta[0]), id(lsta[1]),id(lsta[2]))
10. print(id(lsta1[0]), id(lsta1[1]), id(lsta1[2]))
11.
12. # 2310617518336
13. # 2310617599488
14. # 140732194690720 140732194690752 140732194690784
15. # 140732194690720 140732194690752 140732194690784
16.
17. print(id(lstb))
18. print(id(lstb1))
19. print(id(lstb[0]), id(lstb[2]), id(lstb[2][0]))
20. print(id(lstb1[0]), id(lstb1[2]), id(lstb1[2][0]))
21.
22. # 2310617599744
23. # 2310617608704
24. # 140732194690720 2310617532800 140732194690784
25. # 140732194690720 2310617608640 140732194690784

对于可变对象(列表、字典、集合):浅拷贝在拷贝时,只会 copy 一层,在内存中开辟一个空间,存放这个 copy 的列表。更深的层次并没有 copy,即第二层用的都是同一个内存;深拷贝时,会逐层进行拷贝,遇到可变类型,就开辟一块内存复制下来,遇到不可变类型就沿用之前的引用。因为不可变数据修改会从新开辟新的空间,所以,深拷贝数据之间的修改都不会相互影响。

三、总结:

  • 浅拷贝花费时间少,占用内存少,只拷贝顶层数据,拷贝效率高。
  • 对不可变对象拷贝时,浅拷贝和深拷贝的作用是一致的,不开辟新空间,相当于赋值操作。
  • 可变对象浅拷贝时,只拷贝第一层中的引用,如果元素是可变对象,并且被修改,那么拷贝的对象也会发生变化。
  • 可变对象深拷贝时,会逐层进行拷贝,遇到可变类型,就开辟一块内存复制下来。