代码之家  ›  专栏  ›  技术社区  ›  Anurag Uniyal

如何存储回调方法?

  •  2
  • Anurag Uniyal  · 技术社区  · 16 年前

    我正在尝试存储一些方法回调,但引用它会使绑定对象保持活动,所以我尝试保持对方法的弱链接,但这似乎不可能?

    所以

    • 为什么我不能保持对方法的弱引用(见下面的示例)

    • 保持方法引用的最佳方法是什么?标准库中有什么东西吗?或者我必须将函数和对象引用分开?

    例子:

    import weakref
    
    class A(object):
        def m(self): pass
    
    a = A()
    
    import weakref
    
    class A(object):
        def m(self): pass
    
    a = A()
    
    rm = weakref.ref(a.m)
    print "is weak ref to method dead?",rm() is None
    print "Q1. why can't i keep weakref to bound method?"
    
    ra = weakref.ref(a)
    m = a.m
    print "delete object"
    del a
    print "is object dead?",ra() is None
    print "delete method"
    del m
    print "is object dead?",ra() is None
    print "Q2. hmmm so i am stuck i can't keep a ref as it stops the object from gc, but weakref to method isn't working?"
    
    4 回复  |  直到 16 年前
        1
  •  0
  •   Community Mohan Dere    9 年前

    我问过 the same question here !在我的问题中,我谈到了gobject,但认识到它是任何类型的Python中的一个普遍问题!我在那里得到了lioro的帮助,我在当前代码中使用的代码如下。一些要点:

    • 不能为方法对象断奶。您必须对实例及其函数属性进行weakeref,或者只使用方法名(正如我在下面的代码中所做的那样)

    • 您可以添加一些机制来在连接的对象离开时注销回调,如果不这样做,您将使weakcallback对象处于活动状态,并在偶数发生时执行空方法。

    .

    class WeakCallback (object):
        """A Weak Callback object that will keep a reference to
        the connecting object with weakref semantics.
    
        This allows object A to pass a callback method to object S,
        without object S keeping A alive.
        """
        def __init__(self, mcallback):
            """Create a new Weak Callback calling the method @mcallback"""
            obj = mcallback.im_self
            attr = mcallback.im_func.__name__
            self.wref = weakref.ref(obj, self.object_deleted)
            self.callback_attr = attr
            self.token = None
    
        def __call__(self, *args, **kwargs):
            obj = self.wref()
            if obj:
                attr = getattr(obj, self.callback_attr)
                attr(*args, **kwargs)
            else:
                self.default_callback(*args, **kwargs)
    
        def default_callback(self, *args, **kwargs):
            """Called instead of callback when expired"""
            pass
    
        def object_deleted(self, wref):
            """Called when callback expires"""
            pass
    

    使用说明:

    # illustration how I typically use it
    weak_call = WeakCallback(self._something_changed)
    long_lived_object.connect("on_change", weak_call)
    

    我用 WeakCallback.token 我在子类中创建的属性,用于在连接程序离开时断开回调连接。

        2
  •  3
  •   mthurlin    16 年前

    由于方法绑定到对象,如果对象不存在,您希望如何处理它?自我包含什么?

    如果方法中不需要该对象,请将其设置为类方法。那么您的对象将是gc:d,即使您对该方法有一个正常的引用。

        3
  •  2
  •   Alex Martelli    16 年前

    在python食谱中,“保持对绑定方法的引用而不抑制垃圾收集”,提供了一个非常彻底但简明的讨论和解决方案。你可以在线阅读(在谷歌图书上) here ;我们将该食谱归功于Knapka、Jolliton和Nicodemus(部分来源于已经提到的另一个答案的原始Activestate食谱),当然,正如食谱中通常的那样,我们(我、我的妻子Anna和David Ascher)负责整个讨论流程和为打印选择的确切代码版本。G,所以,如果有什么问题,那就是 我们的 故障;-)

        4
  •  0
  •   Bruno Oliveira    16 年前

    他们有一个很好的解决方案:

    http://code.activestate.com/recipes/81253/

    看看最后一个匿名发布的例子。