繁体   English   中英

如何在类中使用装饰器

[英]how to use decorator in a class

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

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()   

但是,有这样的错误:

@record_log(self.logs)
NameError: name 'self' is not defined

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

非常感谢!

此时您无法传递对self或任何self属性的引用。 在执行main代码之前,即在创建任何MyClass实例之前执行@record_log行(方法被修饰) - 事实上,甚至在MyClass的定义完成之前! 但请记住

@record_log(self.logs) 
def test(self, n):

实际上只是语法糖

test = record_log(self.logs)(test)

因此解决问题的一种方法是在__init__重新定义test ,即

def __init__(self, log_location)
    self.logs = logging(log_location)
    self.test = record_log(self.logs)(self.test)

另请注意,您的装饰器未将任何参数传递给func而不返回结果。 此外,它应该在模块级别(在课前)定义。

def record_log(log_object): 
    def deco(func):
        def wrap(*args, **kwargs):
            rs = func(*args, **kwargs)   # pass parameters
            if rs:
                log_object.record('success')
            else:
                log_object.record('fail')
            return rs   # return result
        return wrap
    return deco

您的代码有几个异议:

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

  2. 如果您只打算装饰MyClass的方法,那么将log_object传递给装饰器是没有意义的,因为将始终使用self.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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM