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

2023-11-29

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

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():
    ...

这非常有效,直到我需要在类中执行此操作 - 函数被装饰before它绑定到类,这意味着给定的回调函数无法获取拥有它的类的实例,从而使其无用。有办法让它发挥作用吗?


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

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

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

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

然后我们使用检查模块找到标记函数的绑定版本,并将它们连接起来:

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__是原始未绑定函数的名称。这使我们能够访问之前应用的标记,从而方便我们夺回.

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

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

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

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

编辑:我在 github 上发布了一个小型库,可以为您完成此操作 - 它称为recap.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从装饰器获取对实例方法的引用 的相关文章

  • 在Python中使用字典作为switch语句[重复]

    这个问题在这里已经有答案了 我正在尝试使用字典用 Python 制作一个简单的计算器 这是我的代码 def default print Incorrect input def add a b print a b def sub a b pr
  • Pandas 字符串提取所有匹配项

    我正在学习 pandas 系列字符串方法中的正则表达式操作 我能够从字符串中提取第一个数字 但我的正则表达式与第二个数字不匹配 如何捕获这两个数字 注意第二行 第二个元素在这里是 NAN CODE import pandas as pd d
  • Spyder 导入模块出错

    我正在尝试在 Spyder 中使用 sklearn 一开始 当我尝试导入它时 我收到 ImportError No module named sklearn 然后我用 PYTHONPATH 管理器设置 PATH 然后使用工具菜单中的 更新模
  • Django 未在 404 页面上应用应用程序中的 CSS 文件

    姜戈3 0 8 Python 3 7 x 我有一个包含一些应用程序的 Django 项目 我正在尝试为 400 403 404 500 错误制作一些 默认 错误页面 我已经这样做了 并显示了适当的模板 但没有任何样式或 JS 在 404 错
  • 在 vim 折叠线中语法高亮 Python

    我发现代码折叠 http en wikipedia org wiki Code folding帮助我更好地组织我的文件 因此 在我的底部 vimrc 我启用vim代码折叠 http vimdoc sourceforge net htmldo
  • 类型错误:需要 Future 或协程

    我尝试在 asyncssh 上自动重新连接 ssh 客户端 SshConnectManager 必须留在后台并在需要时进行 ssh 会话 class SshConnectManager object def init self host u
  • 如何在Python中求和

    我想知道如何在 python 中表示总和而不需要像这样的循环here http docs scipy org doc scipy reference tutorial optimize html 我们有 def rosen x The Ro
  • python:是否有用于对输入流进行分块的库函数?

    我想对输入流进行分块以进行批处理 给定一个输入列表或生成器 x in 1 2 3 4 5 6 我想要一个能够返回该输入块的函数 说 如果chunk size 4 then x chunked 1 2 3 4 5 6 这是我一遍又一遍地做的事
  • 如何在交互式绘图(Python)中获得鼠标指向的(x,y)位置?

    我使用 ipython 笔记本 带有魔法 matplotlib nbagg 我正在审查matplotlib widget Cursor但仅查看光标widgets Cursor http matplotlib org 1 4 3 exampl
  • 如何测试列表中多个值的成员资格

    我想测试两个或多个值是否在列表中具有成员资格 但我得到了意外的结果 gt gt gt a b in b a foo bar a True 那么 Python 可以同时测试列表中多个值的成员资格吗 这个结果意味着什么 See also How
  • 如何修改 contenteditable 元素的innerHTML

    我使用 Selenium 与 Chrome driver 和 python3 6 来测试网站 我在网页中有代码片段如下 div class 3F6QL 2WovP div class 39LWd Type a message div div
  • 如何加速 pandas 字符串函数?

    我正在使用 pandas 矢量化 str split 方法来提取从 上的拆分 返回的第一个元素 我还尝试使用 df apply 与 lambda 和 str split 来产生等效的结果 使用 timeit 时 我发现 df apply 的
  • Qcut Pandas:ValueError:Bin 边缘必须是唯一的

    我使用 Pandas 中的 Qcut 将数据离散化为大小相等的存储桶 我想要有价格桶 这是我的数据框 productId sell prix categ popularity 11997 16758760 0 28 75 50 524137
  • Python 中的十进制到二进制半精度 IEEE 754

    我只能使用以下命令将十进制转换为二进制单精度 IEEE754struct pack模块 或者使用相反的方法 float16 或 float32 numpy frombuffer 是否可以使用 Numpy 将十进制转换为二进制半精度浮点数 我
  • Python 队列 get()/task_done() 问题

    我的消费者端队列 m queue get queue task done
  • 如何保持 python 3 脚本 (Bot) 运行

    不是母语英语 抱歉 英语可能很蹩脚 我也是编程新手 您好 我正在尝试使用 QueryServer 连接到 TeamSpeak 服务器来创建机器人 经过几天的努力 它有效 只有 1 个问题 而我却被这个问题困扰了 如果您需要检查 这是我正在使
  • Matplotlib 中的 TwoSlopeNorm 未按预期工作

    我正在尝试创建一个具有发散颜色图的绘图 该颜色图在零附近不对称 In this https stackoverflow com a 20146989 6288682例如 DivergingNorm函数被使用并产生我想要的 然而 我使用的是更
  • 在多个图表上绘制一条线

    I don t know how this thing is called or even how to describe it so the title may be a little bit misleading The first a
  • 通过 ManyToManyField = Value 对 django 查询集进行排序

    如果有一些模型 例如 class Tag models Model name models CharField class Thing models Model title models CharField tags models Many
  • django admin 中内联模型的分页器

    我有这个简单的 django 模型 由一个传感器和特定传感器的值组成 每个日射强度计的值数量很多 gt 30k 是否可以以某种方式分页PyranometerValues在特定日期或一般情况下将分页器应用于管理内联视图 class Pyran

随机推荐