我今天写了这样的东西(与mpl_connect文档不同:
class Foo(object):
def __init__(self): print 'init Foo', self
def __del__(self): print 'del Foo', self
def callback(self, event=None): print 'Foo.callback', self, event
from pylab import *
fig = figure()
plot(randn(10))
cid = fig.canvas.mpl_connect('button_press_event', Foo().callback)
show()
Run Code Online (Sandbox Code Playgroud)
这看起来很合理,但它不起作用 - 就好像matplotlib失去了我给它的功能.如果不通过它Foo().callback我通过它lambda e: Foo().callback(e),它的工作原理.同样,如果我说x = Foo(),然后通过它x.callback,它的工作原理.
我的假设是,创建的未命名的Foo实例会在行Foo()之后立即销毁mpl_connect- 具有Foo.callback引用的matplotlib 不会保持Foo活动状态.那是对的吗?
在我遇到的非玩具代码中,解决方案x = Foo()没有用,大概是因为在那种情况下show()其他地方x已经超出了范围.
更一般地说,Foo().callback是一个<bound method Foo.callback of <__main__.Foo object at 0x03B37890>>.我的主要惊喜是,似乎绑定方法实际上并没有保持对对象的引用.那是对的吗?
是的,绑定方法引用对象 - 对象是绑定方法对象的.im_self属性的值.
所以,我想知道是否matplotlibS" mpl_connect()是记住递增传递给它的参数的引用计数.如果不是(这是一个常见的错误),那么返回Foo().callback时没有什么可以保持匿名活着mpl_connect().
如果您可以轻松访问源代码,请查看mpl_connect()实现?你想看到C代码在做什么Py_INCREF();-)
编辑这看起来很相关,来自这里的文档:
画布仅保留对回调的弱引用.因此,如果回调是类实例的方法,则需要保留对该实例的引用.否则,实例将被垃圾收集并且回调将消失.
所以这是你的错 - LOL ;-)
| 归档时间: |
|
| 查看次数: |
681 次 |
| 最近记录: |