创建具有嵌套的weakref的类实例的深层副本

编程入门 行业动态 更新时间:2024-10-27 11:27:55
本文介绍了创建具有嵌套的weakref的类实例的深层副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

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

I have two classes: a parent class and a container class. The parent class instance has matching container class instance as a weak reference.

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

There is a problem while deep copying the parent instance, the weakref is still linking to the original instance. Here is a minimal example:

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 __ 魔术方法可以实现,但不确定具体如何。

I suspect that the __deepcopy__ magic method can be implemented, but not sure how exactly.

推荐答案

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

The problem is that deepcopy won't follow the weakref.ref link. It doesn't even copy the weakref.ref:

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

即已明确硬编码在 copy 模块中 。我不知道为什么会这样,但是我怀疑他们有他们的原因。

That is explicitly hardcoded in the copy module. I don't know why this is but I suspect they had their reasons.

但是您可以实现 __ 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): # set __deepcopy__ element to "false"-ey value so we don't go into # recusion. self.__deepcopy__ = None try: new = deepcopy(self, memo) finally: # Always delete the self.__deepcopy__ again, even if deepcopying failed del self.__deepcopy__ del new.__deepcopy__ # remove the copied __deepcopy__ attribute 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()

由于临时的 __ deepcopy __ 实例属性,这有点难看。但是它允许在 self 上使用普通的 deepcopy 函数,而无需进行无限递归,那么您只需要手动创建

It's a bit ugly because of the temporary __deepcopy__ instance attribute. But it allows to use the normal deepcopy function on self without going into infinite recursions and then you only have to manually create a new weak reference to your parent.

您甚至可以在不临时设置 __ deepcopy __ 的情况下进行操作(它应该可以正常工作):

You could even do it without temporarily setting __deepcopy__ (it should work correctly):

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()

更多推荐

创建具有嵌套的weakref的类实例的深层副本

本文发布于:2023-11-25 14:23:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1630112.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:嵌套   副本   实例   weakref

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!