Python 如何从装饰器获取对实例方法的引用

Python 如何从装饰器获取对实例方法的引用,python,callback,signals,decorator,Python,Callback,Signals,Decorator,我一直在使用GUI库,该库允许您使用connect函数将信号连接到信号处理程序,例如: widget.connect(signal, callback) 意味着每当小部件触发信号时,将运行函数回调。为了使我的代码变得更好,并从构造函数中删除一系列的connect调用,我决定使用一个decorator,它工作得很好: def callback(widget, signal) def decorate(f): widget.connect(signal, f)

我一直在使用GUI库,该库允许您使用connect函数将信号连接到信号处理程序,例如:

widget.connect(signal, callback)
意味着每当小部件触发信号时,将运行函数
回调
。为了使我的代码变得更好,并从构造函数中删除一系列的
connect
调用,我决定使用一个decorator,它工作得很好:

def callback(widget, signal)
    def decorate(f):
            widget.connect(signal, f)
            return f
    return decorate

...

@callback(widget, signal)
def do_something():
    ...

在我需要在一个类中执行此操作之前,它一直工作得很好-函数在绑定到该类之前被修饰,这意味着给定的回调函数没有得到拥有它的类的实例,这使得它毫无用处。有什么方法可以让它工作吗?

一个相对简单的解决方案是可能的。我们首先使用decorator来标记函数。构造实例时,我们搜索这些标记并注册回调

更具体地说,mark-and-recapture模式的工作原理是使用decorator在绑定函数之前对其进行标记,然后在构造函数中实例的绑定方法中找到它

首先,我们使用装饰器进行标记(我们使用一个集合来允许在一个方法上使用多个标记):

然后,我们使用查找标记函数的绑定版本,并连接它们:

def connect_callbacks(obj):
    for _, f in inspect.getmembers(obj, inspect.ismethod):
        try:
            marks = f.__func__._marks
        except AttributeError:
            continue
        for widget, signal in marks:
            widget.connect(signal, f)
\uuuu func\uuu
是原始未绑定函数的名称。这使我们能够访问我们早些时候应用的标记,便于我们重新捕获

然后,我们可以简单地创建类并修饰函数,记住在构造函数中连接回调:

class Test:
    def __init__(self):
        ...
        connect_callbacks(self)

    @callback(widget, signal)
    def test():
        ...
这允许我们将绑定的方法与装饰器连接起来

编辑:我已经在github上发布了一个小型库,它为您提供了这个功能,名为

class Test:
    def __init__(self):
        ...
        connect_callbacks(self)

    @callback(widget, signal)
    def test():
        ...