如何存储回调方法?

时间:2009-11-04 12:25:47

标签: python methods weak-references

我正在尝试存储一些方法回调,但是引用它会使绑定对象保持活动状态,所以我试图将弱参数保留给方法,但这似乎不可能?

所以

  • 为什么我不能保持弱参考。方法(见下面的例子)

  • 保留方法参考的最佳方法是什么?标准库中的任何东西?或者我将不得不保持功能和对象参考。分离

示例:

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 个答案:

答案 0 :(得分:3)

由于该方法绑定到该对象,如果该对象不存在,您希望用它做什么?自己会包含什么?

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

答案 1 :(得分:2)

Python Cookbook中的6.10节“在不禁止垃圾收集的情况下保留对绑定方法的引用”,提供了一个非常简洁的讨论和解决方案。您可以在线阅读(在Google图书上)here;我们把这个食谱归功于Knapka,Jolliton和Nicodemus(部分来自最初的另一个答案已经提到过的有效状态菜谱配方),当然,像在Cookbook中一样,我们(我,我的妻子Anna和David Ascher)是负责整个讨论流程和选择打印的确切代码版本,因此,如果出现问题,那就是我们的错误; - )。

答案 2 :(得分:0)

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

  • 您无法弱化方法对象。你必须弱化实例及其函数属性,或者只是方法名称(就像我在下面的代码中所做的那样)

  • 您可以添加一些机制来在您的连接对象消失时取消注册回调,如果您不这样做,您将改为使用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属性来管理当连接器消失时断开回调

答案 3 :(得分:0)

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

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

看一下Anonymous发布的最后一个例子。