Python 方法decorator来注册回调

Python 方法decorator来注册回调,python,Python,我正在用Python开发一个回调系统。待回调是类的方法。我向装饰师登记这些。 下面是一些表示以下内容的伪类: class MyClass(ABC): def __init__(self): self.cb_stack = {} def register_callback(self, callback, name): self.cb_stack[name] = callback @register_callback('mycb') def myCall

我正在用Python开发一个回调系统。待回调是类的方法。我向装饰师登记这些。 下面是一些表示以下内容的伪类:

class MyClass(ABC):
  def __init__(self):
    self.cb_stack = {}

  def register_callback(self, callback, name):
    self.cb_stack[name] = callback     

  @register_callback('mycb')
  def myCallback(self, input):
    self.do_things()
我怀疑每个装饰都是默认执行的

但是,我希望在调用
obj.myCallback()
时执行decorator,并防止
myCallback()
此时执行(这里应该是这种情况)

我的另一种选择是为每个回调编写长格式,其工作原理如下:

class MyClassLong(ABC):
  def __init__(self):
    self.cb_stack = {}

  def register_callback(self, callback, name):
    self.cb_stack[name] = callback     

  def myCallback(self):
    def func(self, input): 
      self.do_things()
    self.register_callback(func, 'mycb')
请注意,它添加了两行代码,因此这不是一个真正的问题,而是如何使某些东西变得干净。
是否有人知道如何实现,以及如何实现?

因此,您的两个版本都有一个参数
input
,该参数被忽略,但两次都指向一个不同的函数,因此我不知道您到底想要什么,但如果我们去掉它,您可以简单地使用:

class MyClass(ABC):
  def __init__(self):
    self.cb_stack = {}

  def register_callback(self, callback, name):
    self.cb_stack[name] = callback     

  def myCallback(self):
    self.register_callback(self.do_things, 'mycb')

声明类时,类和方法定义只处理一次,因此只能在类级别(而不是实例级别)使用装饰器。如果回调列表应用于类的所有实例,则可以定义一个参数化装饰器来注册它们:

# defines a callback list as a dictionary
# provides the decorator

class Callbacks(dict):        
    def register(self,name):
        def decorate(f):
            self[name] = f         
            return f
        return decorate

class MyClass:

    cb_stack = Callbacks() 

    @cb_stack.register('mycb')
    def myCallback(self, param):
        print("myCallback called",param)

    def triggerCallbacks(self):
        for n,f in type(self).cb_stack.items(): f(self,n)

mc = MyClass()

mc.triggerCallbacks() 

myCallback called mycb
您也可以对子类使用此选项:

class MySubclass(MyClass):
    
    cb_stack = Callbacks(MyClass.cb_stack)
    
    @cb_stack.register('mycb2')
    def myCallback2(self, param):
        print("myCallback2 called",param)

msc = MySubclass()

msc.triggerCallbacks() 

myCallback called mycb
myCallback2 called mycb2

从根本上说,你们都是装修工。首先,您的装饰程序不会返回任何东西,因此
self.myCallback
将是
None
,并且它没有正确处理其他参数,并且会抛出
TypeError
。此外,
self.cb_stack={}
会抛出一个
namererror
我添加了一个正确的
init
,为了简单起见,我先省略了它。实际上,我的回调不应该返回任何内容:它将被添加到dict
self.cb_堆栈中不,你不明白你实际上删除了你的回调。在运行
@register\u callback('mycb')
之后,就没有更多的函数了,实际上,这是由于参数处理不正确而导致的错误。这完全是错误的,就像我说的,你似乎不了解装饰师。装饰师需要返回callableOk谢谢你提供的信息。你能提供一个关于如何正确处理参数的例子,以便我理解这一点吗?然后我将使用第二个(“long”)选项:)有一个额外的函数执行回调堆栈,它看起来像:
def exec(self,input):for cb in self.cb_stack:cb(input)
(所有回调都在相同的输入上工作,就像管道一样)。您的建议与“长”版本相匹配,这样做确实更简单:)