如何在 class 中使用装饰器
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
的任何属性。 @record_log
行在 main
中的代码执行之前执行(该方法被修饰),即在 MyClass
的任何实例创建之前——事实上,甚至在定义之前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
,也没有返回结果。此外,它可能应该在模块级别定义(在 class 之前)。
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
对您的代码有几点异议:
deco()
是多余的。可以直接从record_log()
.
returnwrap
如果你只打算装饰 MyClass
的方法,那么将 log_object
传递给装饰器是没有意义的,因为 self.logs
将永远是用过的。否则,请考虑将装饰器移动到模块级别,正如其他人已经建议的那样。
装饰方法的 return 值当前丢失。
修饰函数的调用没有传递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
我知道有类似的问题,但我的场景有些不同:参考代码:
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
的任何属性。 @record_log
行在 main
中的代码执行之前执行(该方法被修饰),即在 MyClass
的任何实例创建之前——事实上,甚至在定义之前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
,也没有返回结果。此外,它可能应该在模块级别定义(在 class 之前)。
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
对您的代码有几点异议:
deco()
是多余的。可以直接从record_log()
. return如果你只打算装饰
MyClass
的方法,那么将log_object
传递给装饰器是没有意义的,因为self.logs
将永远是用过的。否则,请考虑将装饰器移动到模块级别,正如其他人已经建议的那样。装饰方法的 return 值当前丢失。
修饰函数的调用没有传递
self
给它
wrap
因此,正确的代码应该是:
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