在Python中使用弱引用的正确方法

时间:2016-07-29 14:13:55

标签: python weak-references

我有两个班级Parent和Child。在任何时间点,只有一个Parent,但可以有多个Child对象。 Parent将需要在子名称索引的字典中继续引用Child对象。 Child还需要对Parent的引用,因为它可以调用Parent的一个函数。

我知道我应该在这里使用weakref。我有两种方法可以做到这一点:

方法一

class Child():
    def __init__( self, parent, name ):
        self.parent_ = weakref.proxy( parent )
        self.name_ = name

class Parent():
    def __init__( self ):
        self.children = {}
    def createChild( self, name ):
        self.children[ name ] = Child( self, name )

方法二

class Child():
    def __init__( self, parent, name ):
        self.parent_ = parent
        self.name_ = name

class Parent():
    def __init__( self ):
        self.children = {}
    def createChild( self, name ):
        self.children[ name ] = Child( weakref.proxy( self ), name )
  1. 方法一和方法二有区别吗?
  2. 实现此功能的最佳方法是什么?
  3. 编辑:当父母去世时,孩子也应该死。如果Parent不存在,我不希望存在任何Child对象。

3 个答案:

答案 0 :(得分:0)

你真的需要弱引用吗?如果您使用的方法只有

self.parent = parent

你会达到你想要做的。对父对象的弱引用将允许父对象被销毁,如果它不再被强烈引用,但在这种情况下,子对象将无法调用父对象的函数,因为对象不存在。

方法1和2看起来和我一样。

[R

答案 1 :(得分:0)

您的两种方法是等效的,它们会评估完全相同的结果。

当您希望引用的对象被垃圾收集时,即使您的()引用仍然存在,也会使用弱引用。在您的情况下,您的$('#contact_groups_select').select2({data: groups_array}); 会定期引用您的Parent个实例,但这些子项只会对其共同父级提供弱引用。这意味着,在某些情况下,即使仍有孩子可能想要使用它,父母也会被垃圾收集。

我认为,您可以在这里使用常规的强引用。

答案 2 :(得分:0)

回答你的问题:

  1. 方法1和2相同。
  2. 一般情况下,无需直接致电weakref.proxy()。在这种情况下,您可以使用WeakValueDictionary,即:
  3.   

    弱引用值的映射类。当没有对该值的强引用时,将丢弃字典中的条目。

    我认为您希望在父类之外(因为如果父项被删除,您希望它仍然存在),其中键标识子项和赋予父项的值。所以你有类似的东西:

    registry = weakref.WeakValueDictionary()
    
    class Child():
        def __init__(self, parent, name):
            self.parent = parent
            self.name = name
    
    class Parent():
        def __init__(self):
            pass
        def createChild(self, name):
            child = Child(self, name)
            registry[child] = self
    

    顺便说一下,名称ChildParent在这里有点令人困惑 - 按惯例,它们暗示Child继承自Parent(在这种情况下,你可以直接在孩子身上调用父方法,而不需要孩子知道父母的姓名。你在这里有一个 has-a 关系,而不是是-a 关系。