如何从deepcopy中排除特定的引用?

时间:2018-05-15 14:03:26

标签: python deep-copy

我有一个对象,它有自己的内容(即某事物的列表)和对它的链接的另一个对象的引用。如何排除对其他对象的引用被深层复制?

from copy import deepcopy
class Foo:
    def __init__(self, content, linked_to):
        self.content = content
        self.linked_to = linked_to

a1 = Foo([[1,2],[3,4]], None)
a2 = Foo([[5,6],[7,8]], a1)

a3 = deepcopy(a2) # <- I don't want there, that a3.linked_to will be copied
# I want that a3.linked_to will still point to a1

a3.linked_to.content.append([9,10])
print a1.content # [[1,2],[3,4]], but I want [[1,2],[3,4], [9,10]] 

1 个答案:

答案 0 :(得分:2)

您的类可以实现__deepcopy__方法来控制它的复制方式。来自copy module documentation

  

为了让类定义自己的副本实现,它可以定义特殊方法__copy__()__deepcopy__()。前者被称为实现浅拷贝操作;没有传递其他参数。调用后者来实现深拷贝操作;它传递了一个参数,即备忘录字典。如果__deepcopy__()实现需要对组件进行深层复制,则应该以组件作为第一个参数并将备注字典作为第二个参数调用deepcopy()函数。

只需返回您的课程的新实例,并且您不希望进行深度复制,只是按原样进行操作。使用deepcopy()功能复制其他对象:

from copy import deepcopy

class Foo:
    def __init__(self, content, linked_to):
        self.content = content
        self.linked_to = linked_to

    def __deepcopy__(self, memo):
        # create a copy with self.linked_to *not copied*, just referenced.
        return Foo(deepcopy(self.content, memo), self.linked_to)

演示:

>>> a1 = Foo([[1, 2], [3, 4]], None)
>>> a2 = Foo([[5, 6], [7, 8]], a1)
>>> a3 = deepcopy(a2)
>>> a3.linked_to.content.append([9, 10])  # still linked to a1
>>> a1.content
[[1, 2], [3, 4], [9, 10]]
>>> a1 is a3.linked_to
True
>>> a2.content is a3.content  # content is no longer shared
False