在类中声明装饰器

时间:2016-07-22 10:37:23

标签: python python-2.7 wrapper decorator python-decorators

我正在尝试在Python中使用自定义包装器/装饰器,并且我想在一个类中声明一个内部,以便我可以打印属性的快照。我从this question尝试过的事情没有成功。

这是我想做的事(注意:这段代码不起作用,我解释下面会发生什么)

class TestWrapper():
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = 0

    def enter_exit_info(self, func):
        def wrapper(*arg, **kw):
            print '-- entering', func.__name__
            print '-- ', self.__dict__
            res = func(*arg, **kw)
            print '-- exiting', func.__name__
            print '-- ', self.__dict__
            return res
        return wrapper

    @enter_exit_info
    def add_in_c(self):
        self.c = self.a + self.b
        print self.c

    @enter_exit_info
    def mult_in_c(self):
        self.c = self.a * self.b
        print self.c


if __name__ == '__main__':
    t = TestWrapper(2, 3)
    t.add_in_c()
    t.mult_in_c()

预期输出为:

-- entering add_in_c
-- {'a': 2, 'b': 3, 'c': 0}
5
-- exiting add_in_c
-- {'a': 2, 'b': 3, 'c': 5}
-- entering mult_in_c
-- {'a': 2, 'b': 3, 'c': 5}
6
-- exiting mult_in_c
-- {'a': 2, 'b': 3, 'c': 6}

但我这段代码给出了

Traceback (most recent call last):
  File "C:\Users\cccvag\workspace\Test\src\module2.py", line 2, in <module>
    class TestWrapper():
  File "C:\Users\cccvag\workspace\Test\src\module2.py", line 18, in     TestWrapper
    @enter_exit_info
TypeError: enter_exit_info() takes exactly 2 arguments (1 given)

如果我尝试@enter_exit_info(self)@self.enter_exit_info,我会得到NameError。我该怎么办?

修改

我首先不需要在类中声明装饰器物理,只要它能够从该类的实例访问属性即可。我认为只能在课堂上宣布它,Rawing's answer证明我错了。

4 个答案:

答案 0 :(得分:11)

您需要明确处理nil

self

这是有效的python,但是在类级别拥有一个不是真正的方法的函数有点奇怪。除非你有充分的理由这样做,否则将装饰器移动到模块级范围会更加惯用。

答案 1 :(得分:2)

您可以直接拦截{props.vehicle.offers.derivative} 参数:

,而不是在类中定义装饰器
self

答案 2 :(得分:2)

TL; DR:你想要的是什么

def enter_exit_info(func):
    def wrapper(self, *arg, **kw):
        print '-- entering', func.__name__
        print '-- ', self.__dict__
        res = func(*arg, **kw)
        print '-- exiting', func.__name__
        print '-- ', self.__dict__
        return res
    return wrapper

请记住

@decorate
def myfunc():
    pass

实际上只是

的语法糖
def myfunc():
    pass
my_func = decorate(my_func)

因此,在您的情况下,装饰函数被装饰器的wrapper函数替换,它的wrapper函数将接收当前实例作为第一个参数。< / p>

编辑:我非常同意其他答案,认为在课堂上定义这个装饰是没有意义的。您不需要它来访问当前实例,因为它是作为函数的第一个参数提供的。 FWIW def语句与class语句中使用的语句没有任何不同,它总是产生一个普通的旧function对象。是什么让这个功能成为一种方法&#34; (以及&#39;自动将当前实例作为第一个参数传递)是属性解析机制,参见https://wiki.python.org/moin/FromFunctionToMethod

答案 3 :(得分:-2)

您希望输出应该是字典格式吗? 如果你不想以字典格式输出你可以尝试这个....

def enter_exit_info(func):         def包装器(* arg,** kw):             打印&#39; - 输入&#39;,func。名称
            res = func(* arg,** kw)             打印&#39; - 退出&#39;,func。名称             返回资源         返回包装器

然后你的输出将是

- 输入add_in_c

5 - 退出add_in_c

- 输入mult_in_c

6 - 退出mult_in_c