防止深度复制期间重复使用引用

fla*_*kes 5 python list memoization deep-copy

考虑以下示例:

from copy import deepcopy

item = [0]
orig = [item, item]
copy = deepcopy(orig)

orig[0][0] = 1
print(f"{orig=} {copy=}")

copy[0][0] = 2
print(f"{orig=} {copy=}")
Run Code Online (Sandbox Code Playgroud)

第一个print输出是我所期望的,因为列表中重复了相同的引用。

orig=[[1], [1]] copy=[[0], [0]]
Run Code Online (Sandbox Code Playgroud)

然而,第二个print让我感到惊讶。

orig=[[1], [1]] copy=[[2], [2]]
Run Code Online (Sandbox Code Playgroud)

我本来希望deepcopy列表中最终会出现两个独立的引用copy。相反,它维护重复的单个列表引用的属性。我猜文档的这一部分提到了这一点:

深层复制构造一个新的复合对象,然后递归地将在原始对象中找到的对象的副本插入其中。

我看到该deepcopy函数有一个memo参数。有没有什么有趣的事情可以用这个参数来防止重复的引用,这样最终的输出就会变成:

orig=[[1], [1]] copy=[[2], [0]]
Run Code Online (Sandbox Code Playgroud)

jua*_*aga 3

如果您的全部目的是复制可能来自 JSON 的数据,即列表、字典、字符串、数字、布尔,那么您可以轻松实现自己的函数:

def copy_jsonlike(data):
    if isinstance(data, list):
        return [copy_jsonlike(x) for x in data]
    elif isinstance(data, dict):
        return {k: copy_jsonlike(v) for k,v in data.items()}
    else:
        return data
Run Code Online (Sandbox Code Playgroud)

它还有一个额外的好处,可能比copy.deepcopy

或者,您最初的解决方案json.loads(json.dumps(data))也不是一个坏主意。