用嵌套weakref创建类实例的deepcopy到i

2024-04-19 00:03:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个类:父类和容器类。父类实例将匹配的容器类实例作为弱引用。在

深度复制父实例时出现问题,weakref仍链接到原始实例。下面是一个最小的例子:

import weakref
from copy import deepcopy


class Container:    
    def __init__(self, parent):
        self.parent = weakref.ref(parent)


class Parent:
    def __init__(self):
        self.container = Container(self)


if __name__ == '__main__':
    parent1 = Parent()
    assert(parent1 is parent1.container.parent())

    parent2 = deepcopy(parent1)
    assert(parent2 is parent2.container.parent())

第二个断言失败。在

我怀疑__deepcopy__魔术方法是可以实现的,但不确定具体如何实现。在


Tags: 实例importselfinitcontainerdef容器class
1条回答
网友
1楼 · 发布于 2024-04-19 00:03:55

问题是deepcopy不会跟随weakref.ref链接。它甚至不复制weakref.ref

>>> from copy import deepcopy
>>> import weakref
>>>
>>> parent1 = Parent()
>>> ref1 = weakref.ref(parent1)
>>> ref2 = deepcopy(ref1)
>>> ref1 is ref2
True

它是显式硬编码的in the ^{} module。我不知道这是为什么,但我怀疑他们有他们的理由。在

但是,您可以实现__deepcopy__方法:

^{pr2}$

由于临时的__deepcopy__实例属性,它有点难看。但是它允许在self上使用普通的deepcopy函数,而无需进行无限递归,然后您只需手动创建一个新的对父对象的弱引用。在

您甚至可以不临时设置__deepcopy__(它应该可以正常工作):

import weakref
from copy import deepcopy

class Container:    
    def __init__(self, parent):
        self.parent = weakref.ref(parent)

class Parent:
    def __init__(self):
        self.container = Container(self)

    def __deepcopy__(self, memo):
        # Create a new class
        new = object.__new__(type(self))
        memo[id(self)] = new   # add the new class to the memo
        # Insert a deepcopy of all instance attributes
        new.__dict__.update(deepcopy(self.__dict__, memo))
        # Manually update the weakref to be correct
        new.container.parent = weakref.ref(new)
        return new

if __name__ == '__main__':
    parent1 = Parent()
    assert parent1 is parent1.container.parent()

    parent2 = deepcopy(parent1)
    assert parent2 is parent2.container.parent()

    parent3 = deepcopy(parent2)
    assert parent3 is parent3.container.parent()

相关问题 更多 >