python - 对类方法使用 pydispatch 和装饰器

标签 python decorator class-method

我正在尝试一些相当简单的事情。我想编写一个装饰器,它使用 pydispatcher 在事件处理程序中转换类方法。这是我的基本方法:

from pydispatch.dispatcher import connect,send,Any

SIGNAL = "test"

def triggered(func):
    connect(func,signal=SIGNAL,sender = Any)
    return func

class P(object):
    @triggered
    def a(self,*args,**kwargs):
        print "yay"

if __name__ == "__main__":
    p = P()
    send(signal=SIGNAL,sender="")

这会引发错误:

Traceback (most recent call last):
  File "util.py", line 35, in <module>
    send(signal=SIGNAL,sender="")
  File "/usr/local/lib/python2.7/dist-packages/pydispatch/dispatcher.py", line 338, in send
    **named
  File "/usr/local/lib/python2.7/dist-packages/pydispatch/robustapply.py", line 55, in robustApply
    return receiver(*arguments, **named)
TypeError: a() takes at least 1 argument (0 given)

有什么想法吗?

最佳答案

您在类中注册了一个函数。这意味着只是注册了函数,而不是绑定(bind)方法。函数未绑定(bind)到实例,因此不会传入 self 参数。

您不能希望在类定义中的常规方法上使用装饰器,因为当时所需的上下文(实例)不可用。

您必须首先创建一个实例,然后注册绑定(bind)到该实例的方法才能使其工作:

class P(object):
    def a(self, *args, **kwargs):
        print "yay"

if __name__ == "__main__":
    p = P()
    triggered(p.a)
    send(signal=SIGNAL,sender="")

现在 triggered() 注册 p.a 绑定(bind)方法;调用该方法将在调用时传入 p 作为 self 参数。

您也可以将a 方法设为静态 方法。静态方法本质上只是一个函数;它从不接受 self 参数。这意味着您可以将其注册为信号处理程序,但您永远无法获得使用类的好处:

class P(object):
    @staticmethod
    @triggered
    def a(*args, **kwargs):
        print "yay"

如果您将其设为类方法,您将获得传入的类(仍然不是实例),并且您将必须在类外部进行注册以确保获得绑定(bind)方法:

class P(object):
    @classmethod
    def a(cls, *args, **kwargs):
        print "yay"

triggered(P.a)

关于python - 对类方法使用 pydispatch 和装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30694722/

相关文章:

python - python中ThreadPool中每个线程的超时

python - 如何在 django 中编写自定义装饰器?

python - 在将函数附加为对象属性的装饰器中使用 functools.partial

javascript - 引用类内的方法

python - 静态方法与类方法的类变量范围

python - 子进程 PIPE 标准输出到两个不同的进程

python - MySQL不存储 float

c# - 如何将枚举发送到 python tcp 服务器?

c# windows-services - 如何处理日志记录异常?

python - 根据类启动参数决定调用哪个类方法