Python | 复制的学问:深复制与浅复制

the usage of threading package

Posted by shawn233 on July 16, 2018

Python中的常见复制不亚于由简到繁三种方式:

  • =复制
  • copy方法复制
  • deepcopy模块复制

我们知道,复制的目的无非是让一个变量具有与另一个变量相同的值。然而,在Python中,限于数据结构的复杂性,复制可能出现一个问题:对副本变量的修改影响到原变量的值(联想C语言中的指针)。

下面讨论怎么选择三种方式以避免出现上面所说的问题。

  • =复制虽用起来简便,但在遇到listdict等复杂的数据结构时,就会出现问题。因此,用=进行复制仅适用于简单的变量(包括int, float等)

  • copy方法是listdict等类型变量自带的一个方法,提供变量的一个副本,但在内部还是用=复制。以list变量复制为例。

Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

>>> a = [1, 2, 3, 4]
>>> b = a.copy()
>>> print (b)
[1, 2, 3, 4]

>>> b[1] = 'a'
>>> print (b)
[1, 'a', 3, 4]
>>> print (a)
[1, 2, 3, 4]

>>> c = [[1, 2, 3], 4]
>>> d = c.copy()

>>> d[0][1] = 'c'
>>> print (d)
[[1, 'c', 3], 4]
>>> print (c)
[[1, 'c', 3], 4]
>>>

可以看出,修改b不会影响a,但修改d中的list元素影响了c中的对应元素。因此,调用copy方法在复杂数据结构嵌套时仍然出现了问题。这就是所谓的浅复制

  • deepcopy模块很好地弥补了copy方法的不足。即使数据结构复杂,副本变量也不再影响原变量。这就是所谓的深复制。注意在使用时需要from copy import deepcopy。这里同样以list类型变量为例。
>>> e = [[1, 2, 3], 4]
>>> from copy import deepcopy
>>> f = deepcopy(e)
>>> print (f)
[[1, 2, 3], 4]

>>> f[0][1] = 'c'
>>> print (f)
[[1, 'c', 3], 4]

>>> print (e)
[[1, 2, 3], 4]
>>>