当前位置: 首页 > 面试题库 >

在Python中实现挂钩或回调的首选方法是什么?

桂丰
2023-03-14
问题内容

我想通过提供一个调用用户函数的接口来为我的一个模块的用户提供扩展其功能的能力。例如,我想让用户能够在创建类的实例时得到通知,并有机会在使用该实例之前对其进行修改。

我实现它的方法是声明一个执行实例化的模块级工厂函数:

# in mymodule.py
def factory(cls, *args, **kwargs):
    return cls(*args, **kwargs)

然后,当我在mymodule中需要一个类的实例时,我会做factory(cls, arg1, arg2)而不是cls(arg1, arg2)

为了扩展它,程序员将在另一个模块中编写如下函数:

def myFactory(cls, *args, **kwargs):
    instance = myFactory.chain(cls, *args, **kwargs)
    # do something with the instance here if desired
    return instance

上面的回调的安装如下所示:

myFactory.chain, mymodule.factory = mymodule.factory, myFactory

这对我来说似乎很简单,但是我想知道作为Python程序员的您是否期望函数注册一个回调而不是通过赋值来完成,或者您是否期望其他方法。我的解决方案对您来说似乎可行,惯用且清晰吗?

我希望将其保持尽可能简单。我认为大多数应用程序实际上并不需要链接多个用户回调,例如(尽管在上述模式下,无限链接“免费”提供)。我怀疑他们是否需要删除回调或指定优先级或顺序。在我看来,像python-
callbacks
或PyDispatcher之类的模块似乎过大了,尤其是后者,但是,如果使用该模块的程序员能够获得引人注目的收益,我就可以接受。


问题答案:

结合了Aaron使用装饰器的想法和Ignacio的类维护维护附加回调列表的类的想法,再加上从C#借用的概念,我想到了:

class delegate(object):

    def __init__(self, func):
        self.callbacks = []
        self.basefunc = func

    def __iadd__(self, func):
        if callable(func):
            self.__isub__(func)
            self.callbacks.append(func)
        return self

    def callback(self, func):
        if callable(func):
            self.__isub__(func)
            self.callbacks.append(func)
        return func

    def __isub__(self, func):
        try:
            self.callbacks.remove(func)
        except ValueError:
            pass
        return self

    def __call__(self, *args, **kwargs):
        result = self.basefunc(*args, **kwargs)
        for func in self.callbacks:
            newresult = func(result)
            result = result if newresult is None else newresult
        return result

使用修饰功能@delegate可以将其他功能“附加”到该功能。

@delegate
def intfactory(num):
    return int(num)

可以使用添加函数+=(使用删除-=)。您还可以装饰funcname.callback以添加回调函数。

@intfactory.callback
def notify(num):
    print "notify:", num

def increment(num):
    return num+1

intfactory += increment
intfactory += lambda num: num * 2

print intfactory(3)   # outputs 8

这听起来像Pythonic吗?



 类似资料:
  • 问题内容: React.js为动画提供了一个低级API,称为ReactTransitionGroup。在文档中指出,对钩,和,一个回调函数作为参数传递。 我的问题是,此回调究竟是什么以及如何传递给这些钩子,文档没有对这些回调进行任何说明,只是将动画延迟到调用之前。 问题答案: 首先,我也仍在学习ReactJS,所以我的方法可能有错误,而没有错误。为此提前致歉。 打开“开发人员工具”的窗口,分析我刚

  • 问题内容: 由于无法更改,因此我想知道如何更有效地连接字符串? 我可以这样写: 或像这样: 问题答案: 将字符串附加到字符串变量的最佳方法是使用+或+=。这是因为它可读且快速。它们的速度也一样快,你选择的是一个品味问题,后者是最常见的。以下是该timeit模块的计时: 但是,那些建议拥有列表并附加到列表然后再连接这些列表的人之所以这样做,是因为与扩展字符串相比,将字符串附加到列表可能非常快。在某些

  • 问题内容: 假设我有一个并发映射,该映射具有高读,低写且需要存储应用程序数据: 然后,在启动过程中并通过用户输入,将数据添加到地图: 如果随后需要更改数据,我应该: A)使Data类对象不可变,然后在每次需要更改Data对象时进行放置操作: B)使用易失性字段,原子引用或最终并发字段,使Data类对象易变但具有线程安全性,只需根据需要修改对象: C)以上都不是 问题答案: A)是更好的选择,原因有

  • 因为Python的不能更改,我想知道如何更有效地连接字符串? 我可以这样写: 或者像这样: 在写这个问题的时候,我发现了一篇谈论这个话题的好文章。 http://www.skymind.com/~ocrow/python_string/ 但是它是在Python2.x中,所以问题是Python3中是否做了一些更改?

  • 本文向大家介绍Python实现Event回调机制的方法,包括了Python实现Event回调机制的方法的使用技巧和注意事项,需要的朋友参考一下 0.背景 在游戏的UI中,往往会出现这样的情况: 在某个战斗副本中获得了某个道具A,那么当进入主界面的时候,你会看到你的背包UI上有个小红点(意思是有新道具),点击进入背包后,发现新增了道具A,显示个数为1,并且在下个界面中有个使用的按钮由灰色不可使用变成

  • 问题内容: 在python中编写文件路径时,我看到了几种写语法的变体,并且我很好奇是否只有一种首选的方式:示例如下: 如果有人可以提供一些指导,将不胜感激。哦,就像信息一样,我的python技能水平是新手。 问题答案: 第一和第二完全相同。就字符数而言,第三个是最短的。此外,在Windows以外的平台上,也支持使用正斜杠作为路径分隔符。但是,如果要对Windows特定路径进行硬编码,那并不是那么重