为什么在不可变列表的浅拷贝和深拷贝之间没有区别

时间:2014-05-19 05:31:34

标签: python python-2.7 python-3.x deep-copy python-internals

假设我有一个由l组成的python列表immutables.当我正在执行浅拷贝深拷贝时,结果是相同的:

>>> a = (1,2) # immutable types
>>> b = (3,4)
>>> l = [a,b] # a list containing immutable types

>>> import copy
>>> y = copy.copy(l) # shallow copy
>>> z = copy.deepcopy(l) # deep copy

>>> id(l[0])
139857440375584
>>> id(y[0])
139857440375584
>>> id(z[0])
139857440375584 # all have the same id's , so all refer to the same object

这是否意味着浅拷贝深拷贝仅对mutable类型的集合有意义,因为immutable类型永远不会更改。 但是,如果我们想要为这些类型的集合实现深层复制行为,我们该怎么做呢?

问候。

3 个答案:

答案 0 :(得分:3)

由于您无法更改不可变对象,因此在复制时创建相同副本毫无意义。

浅拷贝

根据copy's source code,不可变类型的浅层副本就像这样完成

def _copy_immutable(x):
    return x

for t in (type(None), int, long, float, bool, str, tuple,
          frozenset, type, xrange, types.ClassType,
          types.BuiltinFunctionType, type(Ellipsis),
          types.FunctionType, weakref.ref):
    d[t] = _copy_immutable

对于所有不可变类型,_copy_immutable函数在浅层复制期间返回对象。

深层复制

同样,在元组的深度复制过程中,对象按原样返回,按照_deepcopy_tuple function

d = id(x)
try:
    return memo[d]

答案 1 :(得分:2)

thefourtheye解释了为什么没有区别。如果你想要做到这一点,你可以通过酸洗来解决它:

import pickle

a = (1,2)
b = (3,4)
l = [a,b]

z = pickle.loads(pickle.dumps(l))

print id(l[0])
print id(z[0])

显然,这绝不是必要的。

答案 2 :(得分:0)

对于这种特定情况,优化了创建小整数对象。即使在进行简单的赋值时,您也可以观察到对象的相同标识,即使它们不应该彼此了解:

>>> a = 1
>>> b = 5
>>> c = 1
>>> d = 5
>>> id(a)
1815461288
>>> id(c)
1815461288
>>> id(b)
1815461352
>>> id(d)
1815461352