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

标签 python callback signals decorator

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

widget.connect(signal, callback)

意味着函数 callback 将在小部件发出信号时运行。为了让我的代码更好,并从我的构造函数中删除一系列 connect 调用,我决定使用一个装饰器,效果很好:

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

...

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

在我需要在类中执行此操作之前,此方法非常有效 - 该函数在 绑定(bind)到类之前被修饰,这意味着给定的回调函数不会获得类的实例拥有它,让它变得毫无用处。有没有办法让它发挥作用?

最佳答案

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

更具体地说,标记和重新捕获模式的工作原理是使用装饰器在函数绑定(bind)之前对其进行标记,然后在构造函数中实例的绑定(bind)方法中找到它。

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

def callback(*args):
    def decorate(f):
        try:
            f._marks.add(args)
        except AttributeError:
            f._marks = {args}
        return f
    return decorate

然后我们使用the inspect module找到标记函数的绑定(bind)版本,并连接它们:

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)

__func__ 是原始未绑定(bind)函数的名称。这使我们能够访问我们之前应用的标记,便于我们重新捕获

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

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

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

这允许我们将绑定(bind)方法与装饰器连接起来。

编辑:我已经在 github 上发布了一个小型库来为您完成这项工作 - 它叫做 recap .

关于python - 如何从装饰器中获取对实例方法的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12078877/

相关文章:

Python 子进程用完文件描述符

python - 并非所有行都被添加到 SearchCursor 中的列表中

python - 将 pandas 字典列拆分为多列

linux - 如何在多线程应用程序中使用异步信号管理共享 POSIX 信号量

c++ - 为什么 signalhandler 不输出任何东西?

python - URL 查询字符串中字段名称的多个值?

javascript - 如何将额外参数传递给 Javascript .filter() 方法中的回调函数?

ruby-on-rails - 如何避免循环

javascript - 直接调用方法和使用 '.call' 方法的区别? JS

c++ - C++:在SIGUSR信号上序列化对象