如何用装饰器类装饰实例方法?

考虑这个小例子:


import datetime as dt


class Timed(object):

    def __init__(self, f):

        self.func = f


    def __call__(self, *args, **kwargs):

        start = dt.datetime.now()

        ret = self.func(*args, **kwargs)

        time = dt.datetime.now() - start

        ret["time"] = time

        return ret


class Test(object):

    def __init__(self):

        super(Test, self).__init__()


    @Timed

    def decorated(self, *args, **kwargs):

        print(self)

        print(args)

        print(kwargs)

        return dict()


    def call_deco(self):

        self.decorated("Hello", world="World")


if __name__ == "__main__":

    t = Test()

    ret = t.call_deco()

哪个打印


Hello

()

{'world': 'World'}

为什么self参数(应该是Test obj实例)没有作为第一个参数传递给装饰函数decorated?


如果我手动进行操作,例如:


def call_deco(self):

    self.decorated(self, "Hello", world="World")

它按预期工作。但是,如果我必须事先知道某个函数是否装饰,它就破坏了装饰器的全部目的。这里的模式是什么,还是我误会了什么?


白板的微信
浏览 874回答 3
3回答

慕码人2483693

您首先必须了解函数如何成为方法以及如何self“自动”注入。一旦知道这一点,“问题” 就很明显了:您正在decorated用Timed实例装饰函数-IOW Test.decorated是Timed实例,而不是function实例-并且您的Timed类不会模仿协议的function类型实现descriptor。您想要的内容如下所示:import typesclass Timed(object):    def __init__(self, f):        self.func = f    def __call__(self, *args, **kwargs):        start = dt.datetime.now()        ret = self.func(*args, **kwargs)        time = dt.datetime.now() - start        ret["time"] = time        return ret   def __get__(self, instance, cls):                  return types.MethodType(self, instance, cls)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python