如何在类中使用装饰器

Spy*_*dai 5 python decorator python-decorators

我知道有类似的问题,但我的情况有所不同:参考代码:

class MyClass(object):
    def __init__(self, log_location)
        self.logs = logging(log_location) # create log object by the log_location, this object should be used by the decorator fucntion

    def record_log(log_object): 
        """ this is the decorator function
        """
        def deco(func):
            def wrap(*args, **kwargs):
                rs = func()

                # use log object to record log
                if rs:
                    log_object.record('success')
                else:
                    log_object.record('fail')

            return wrap
        return deco

   @record_log(self.logs) 
   def test(self):
       rs = do_some_thing
       if rs:
            return True
       return False

def main():
    my_class = MyClass()
    my_class.test()   
Run Code Online (Sandbox Code Playgroud)

但是,有一个这样的错误:

@record_log(self.logs)
NameError: name 'self' is not defined
Run Code Online (Sandbox Code Playgroud)

在这样的场景中,我应该在装饰器函数中使用实例属性 self.logs 吗?

非常感谢!

Vad*_*nda 1

对于您的代码有几个反对意见:

  1. deco()是多余的。可以直接wrap从回来record_log()

  2. 如果您只打算装饰的方法,那么传递给装饰器MyClass是没有意义的,因为它将始终被使用。否则,请考虑将装饰器移动到模块级别,正如其他人已经建议的那样。log_objectself.logs

  3. 装饰方法的返回值当前丢失。

  4. 对修饰函数的调用不会传递self给它。

因此,正确的代码是:

class MyClass(object):
    def __init__(self, log_location):
        self.logs = logging(log_location)

    def record_log(func):
        """ this is the decorator function
        """
        def wrap(self):
            rs = func(self)
            # use log object to record log
            if rs:
                print 1
                self.logs.record('success')
            else:
                print 2
                self.logs.record('fail')
            return rs
        return wrap

    @record_log
    def test(self):
       rs = do_some_thing
       if rs:
            return True
       return False
Run Code Online (Sandbox Code Playgroud)