问题基本上是这样的,在 python 的 gobject 和 gtk 绑定中。假设我们有一个在构造时绑定到信号的类:
class ClipboardMonitor (object):
def __init__(self):
clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
clip.connect("owner-change", self._clipboard_changed)
现在的问题是,ClipboardMonitor 的任何实例都不会消亡。 gtk 剪贴板是一个应用程序范围的对象,连接到它会保留对该对象的引用,因为我们使用回调self._clipboard_changed
.
我正在讨论如何使用弱引用(weakref 模块)来解决这个问题,但我还没有拿出一个计划。任何人都知道如何将回调传递给信号注册,并使其表现得像弱引用(如果在 ClipboardMonitor 实例超出范围时调用信号回调,则它应该是无操作)。
添加:独立于 GObject 或 GTK+ 的表述:
如何使用弱引用语义向不透明对象提供回调方法?如果连接对象超出范围,则应将其删除,并且回调应充当无操作;连接者不应持有对连接器的引用。
澄清一下:我明确希望避免调用“析构函数/终结器”方法
标准的方法是断开信号。然而,这需要在您的类中具有类似析构函数的方法,由维护对象的代码显式调用。这是必要的,因为否则你会得到循环依赖。
class ClipboardMonitor(object):
[...]
def __init__(self):
self.clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
self.signal_id = self.clip.connect("owner-change", self._clipboard_changed)
def close(self):
self.clip.disconnect(self.signal_id)
正如您所指出的,如果您想避免显式破坏,则需要弱引用。我会写一个弱回调工厂,例如:
import weakref
class CallbackWrapper(object):
def __init__(self, sender, callback):
self.weak_obj = weakref.ref(callback.im_self)
self.weak_fun = weakref.ref(callback.im_func)
self.sender = sender
self.handle = None
def __call__(self, *things):
obj = self.weak_obj()
fun = self.weak_fun()
if obj is not None and fun is not None:
return fun(obj, *things)
elif self.handle is not None:
self.sender.disconnect(self.handle)
self.handle = None
self.sender = None
def weak_connect(sender, signal, callback):
wrapper = CallbackWrapper(sender, callback)
wrapper.handle = sender.connect(signal, wrapper)
return wrapper
(这是一个概念验证代码,对我有用——您可能应该根据您的需要调整这段代码)。几点注意事项:
- 我分别存储回调对象和函数。您不能简单地创建绑定方法的weakref,因为绑定方法是非常临时的对象。实际上
weakref.ref(obj.method)
创建weakref后会立即销毁绑定的方法对象。我也没有检查是否需要存储函数的弱引用...我想如果你的代码是静态的,你可能可以避免这种情况。
- 当对象包装器注意到弱引用不再存在时,它会将自身从信号发送者中删除。这对于破坏 CallbackWrapper 和信号发送者对象之间的循环依赖也是必要的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)