Python之copy与deepcopy

本文转于Python中 copy, deepcopy 的区别及原因

  • 对于简单的 object,用 shallow copydeep copy 没区别:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    >>> import copy
    >>> origin = 1
    >>> cop1 = copy.copy(origin)
    #cop1 是 origin 的shallow copy
    >>> cop2 = copy.deepcopy(origin)
    #cop2 是 origin 的 deep copy
    >>> origin = 2
    >>> origin
    2
    >>> cop1
    1
    >>> cop2
    1
    #cop1 和 cop2 都不会随着 origin 改变自己的值
    >>> cop1 == cop2
    True
    >>> cop1 is cop2
    True
  • 复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

看代码更容易理解些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> import copy
>>> origin = [1, 2, [3, 4]]
#origin 里边有三个元素:1, 2,[3, 4]
>>> cop1 = copy.copy(origin)
>>> cop2 = copy.deepcopy(origin)
>>> cop1 == cop2
True
>>> cop1 is cop2
False
#cop1 和 cop2 看上去相同,但已不再是同一个object
>>> origin[2][0] = "hey!"
>>> origin
[1, 2, ['hey!', 4]]
>>> cop1
[1, 2, ['hey!', 4]]
>>> cop2
[1, 2, [3, 4]]
#把origin内的子list [3, 4] 改掉了一个元素,观察 cop1 和 cop2

可以看到 cop1,也就是 shallow copy 跟着 origin 改变了。而 cop2 ,也就是 deep copy 并没有变。

似乎 deep copy 更加符合我们对「复制」的直觉定义: 一旦复制出来了,就应该是独立的了。如果我们想要的是一个字面意义的「copy」,那就直接用 deep_copy 即可。

那么为什么会有 shallow copy 这样的「假」 copy 存在呢? 这就是有意思的地方了。

一分一毛也是心意