使用pydispatch和装饰器进行类方法

时间:2015-06-07 14:34:58

标签: 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)

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您在课程中注册了功能。这意味着只是该函数已注册,而不是绑定方法。函数未绑定到实例,因此未传入self参数。

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

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

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绑定方法;调用该方法然后在调用时将p作为self参数传递。

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

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

如果你把它作为一个类方法,你将获得传入的类(仍然不是实例),并且你

你得到一个绑定的方法:

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

triggered(P.a)