如何从装饰器获取对实例方法的引用 [英] How to get a reference to an instance method from a decorator

查看:75
本文介绍了如何从装饰器获取对实例方法的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been using a GUI library that allows you to connect signals to signal handlers using a connect function, for example:

widget.connect(signal, callback)

表示函数 callback 将在小部件中触发信号时运行。为了使我的代码更好,并从构造函数中删除了一系列 connect 调用,我决定使用装饰器,该方法效果很好:

Means that the function callback will be run whenever the signal is fired from the widget. In an attempt to make my code nicer, and remove a series of connect calls from my constructor, I decided to use a decorator, which works well:

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

...

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

在我需要在一个类中完成此功能之前,该功能非常好-函数装饰为 之前,它已绑定到该类,这意味着给定的回调函数不会获得拥有它的类的实例,这使它无用。

This works excellently until I needed to do this in a class - the function is decorated before it is bound to the class, meaning the callback function given doesn't get the instance of the class that owns it, making it useless. Is there a way to get this to work?

推荐答案

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

A relatively simple solution to this is possible. We begin by using the decorator to mark the function. When instances are constructed, we search for these marks and register the callbacks.

更具体地说,标记和捕获模式通过使用装饰器在功能被标记之前进行标记而起作用。绑定,然后在构造函数中实例的绑定方法中找到它。

More specifically, the mark and recapture pattern works by using the decorator to mark the function before it is bound, and then find it amongst the bound methods of the instance in the constructor.

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

First we use a decorator to do the marking (we use a set to allow for multiple marks on one method):

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

然后我们使用检查模块,找到标记功能的绑定版本,并将其连接:

Then we use the inspect module to find the bound versions of the marked functions, and connect them:

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 __ 是原始的未绑定函数的名称。这样一来,我们便可以访问之前应用的标记,从而方便了重新捕获

__func__ is the name of the original, unbound function. This allows us to access the marks that we applied earlier, facilitating our recapture.

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

We can then simply create our class and decorate our functions, remembering to connect our callbacks in the constructor:

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

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

这允许我们将绑定方法与装饰器连接。

This allows us to connect the bound methods with a decorator.

编辑:我在github上发布了一个微型库,可以为您完成此任务-名为概述

I have published a tiny library on github that does this for you - it's called recap.

这篇关于如何从装饰器获取对实例方法的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆