深拷贝是否使用写时复制?

5 投票
3 回答
972 浏览
提问于 2025-04-16 22:14

我想知道,Python 解释器在对可变对象进行深拷贝时,是否会使用“写时复制”的策略。

另外,我也想了解一下,深拷贝是否也会对不可变对象进行操作(不过这对我来说似乎有点奇怪)。

3 个回答

3

我们来看一下:

>>> import copy
>>> x = [[1],[2],"abc"]
>>> y = copy.deepcopy(x)
>>> id(x[0])
4299612960
>>> id(y[0])
4299541608
>>> id(x[2])
4297774504
>>> id(y[2])
4297774504

对于的第一个元素,会进行复制,这样新对象会有一个新的身份标识(id)。而第三个元素是一个不可变的字符串,它不会被复制。

4

不,它并不会这样做,它只是复制对象而已。如果不可变对象引用了可变对象,它也必须复制这些不可变对象。

6

它不支持写时复制。

对于一些内置的不可变类型,它不会进行深拷贝,但任何用户自定义的“不可变”类型都会进行深拷贝。

Python 2.7 标准库中的 copy.py 在文档中包含了以下信息:

这个版本不会复制像模块、类、函数、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口、数组等类型,也不会复制任何类似的类型。

copy 处理不可变对象的方式如下:

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
for name in ("ComplexType", "UnicodeType", "CodeType"):
    t = getattr(types, name, None)
    if t is not None:
        d[t] = _copy_immutable

deepcopy 使用了一种更复杂的方案,内容太长无法在这里全部复制,但大致意思是一样的。有一个有趣的点是,_deepcopy_tuple 会遍历它的元素,直到找到一个被复制的元素才会创建一个新对象。

for i in range(len(x)):
    if x[i] is not y[i]:
        y = tuple(y)
        break
else:
    y = x

撰写回答