在类中声明装饰器

Adr*_*enW 2 python decorator wrapper python-2.7 python-decorators

我试图使用自定义包装/装饰在Python,我想声明一个内部类,这样我就可以,例如打印属性的快照.我从这个问题中尝试过的事情没有成功.


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

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()
Run Code Online (Sandbox Code Playgroud)

预期的产出是:

-- 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}
Run Code Online (Sandbox Code Playgroud)

但我这个代码给出了

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)
Run Code Online (Sandbox Code Playgroud)

如果我尝试@enter_exit_info(self)或者@self.enter_exit_info,我会得到一个NameError.我能做什么?


编辑:

我首先不需要在类中实际声明装饰器,只要它能够从该类的实例访问属性即可.我认为这只能通过在课堂上宣布它来实现,Rawing的回答证明我错了.

wim*_*wim 12

您需要self明确处理.

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

    def enter_exit_info(func):
        def wrapper(self, *arg, **kw):
            print '-- entering', func.__name__
            print '-- ', self.__dict__
            res = func(self, *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()
Run Code Online (Sandbox Code Playgroud)

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

  • 同意.如果留在类定义中,我至少会通过将其名称更改为"_enter_exit_info"来表明它是私有的. (3认同)

Ara*_*Fey 8

您可以截取self参数,而不是在类中定义装饰器:

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

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

    @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()
Run Code Online (Sandbox Code Playgroud)