Python 深拷贝和浅拷贝

任何变成语言中,其实都有浅拷贝和深拷贝的概念,Python 中也不例外。

浅拷贝

浅拷贝是对于一个对象的顶层拷贝。通俗的理解是:拷贝了引用,并没有拷贝内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> a = [1,2,3]
>>> b = a

>>> id(a)
140465763275080
>>> id(b)
140465763275080

>>> b
[1, 2, 3]

>>> a.append(2)
>>> b
[1, 2, 3, 2]

>>> b.append(5)
>>> a
[1, 2, 3, 2, 5]

深拷贝 - copy.deepcopy()

深拷贝是对于一个对象所有层次的拷贝(递归)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 需要引入 copy 模块
>>> import copy
>>> a = [1,2,3]
>>> b = copy.deepcopy(a)
>>> id(a)
140465763275080
>>> id(b)
140465763294408
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3]
>>> b.append(5)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 5]
  • copy.deepcopy 会递归拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> a = [1,2]
>>> b = [3,4]
>>> c = [a,b]
>>> c
[[1, 2], [3, 4]]
>>> d = copy.deepcopy(c)
>>> d
[[1, 2], [3, 4]]
>>> a.append(7)
>>> d
[[1, 2], [3, 4]]
>>> c
[[1, 2, 7], [3, 4]]
  • copy.copy 不会递归拷贝
1
2
3
4
5
6
>>> e = copy.copy(c)
>>> e
[[1, 2, 7], [3, 4]]
>>> a.append(9)
>>> e
[[1, 2, 7, 9], [3, 4]]

拷贝的其他方式

浅拷贝对不可变类型和可变类型的 copy 不同

  • 字典的 copy 方法可以拷贝一个字典

拷贝方式类似于 copy.copy(),即不是递归拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> l = [1,2]
>>> a = dict(name="hoxis", age=18,l=l)
>>> a
{'l': [1, 2], 'age': 18, 'name': 'hoxis'}
>>> b = a.copy()
>>> b
{'l': [1, 2], 'age': 18, 'name': 'hoxis'}
>>> l.append(3)
>>> a
{'l': [1, 2, 3], 'age': 18, 'name': 'hoxis'}
>>> b
{'l': [1, 2, 3], 'age': 18, 'name': 'hoxis'}
>>> a['age'] = 29
>>> b
{'l': [1, 2, 3], 'age': 18, 'name': 'hoxis'}
>>> a
{'l': [1, 2, 3], 'age': 29, 'name': 'hoxis'}
  • 有些内置函数可以生成拷贝(list)
1
2
3
4
5
6
7
8
9
10
11
>>> a = list(range(5))
>>> a
[0, 1, 2, 3, 4]
>>> b = list(a)
>>> b
[0, 1, 2, 3, 4]
>>> a.append(7)
>>> a
[0, 1, 2, 3, 4, 7]
>>> b
[0, 1, 2, 3, 4]
  • 拷贝不可变类型数据

使用 copy.copy() 时,它会根据拷贝对象是否是可变类型,做不同的处理。

比如处理元组时:

1
2
3
4
5
6
>>> a = (1,2,3)
>>> b = copy.copy(a)
>>> id(a)
140465763271376
>>> id(b)
140465763271376
hoxis wechat
一个脱离了高级趣味的程序员,关注回复1024有惊喜~
赞赏一杯咖啡
  • 本文作者: hoxis | 微信公众号【不正经程序员】
  • 本文链接: https://hoxis.github.io/python-copy-deepcopy.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!
0%