Reputation: 179
I know there is similar question, but my scenario is somehow different: refer to codes:
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()
But, there is an error like this:
@record_log(self.logs)
NameError: name 'self' is not defined
Hos should I use the instance attribute self.logs in a decorator function in such scenario like this??
Thanks very much!
Upvotes: 5
Views: 510
Reputation: 2834
There are several objections about your code:
deco()
is redundant. You can directly return wrap
from record_log()
.
If you only plan to decorate MyClass
's methods, then there is no point in passing log_object
to the decorator, as self.logs
will always be used. Otherwise, consider moving the decorator to module level, as already suggested by others.
The decorated method's return value is currently lost.
The call to the decorated function does not pass self
to it.
The proper code would therefore be:
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
Upvotes: 1
Reputation: 82889
You can not pass a reference to self
or any attribute of self
at this point. The @record_log
line is executed (the method is decorated) before the code in main
is executed, i.e. before any instance of MyClass
is created at all -- in fact, even before the definition of MyClass
has been completed! But remember that
@record_log(self.logs)
def test(self, n):
is actually just syntactic sugar for
test = record_log(self.logs)(test)
So one way to work around your problem would be to redefine test
in your __init__
, i.e.
def __init__(self, log_location)
self.logs = logging(log_location)
self.test = record_log(self.logs)(self.test)
Also note that your decorator is not passing any parameters to func
and not returning the results. Also, it should probably be defined on module level (before the 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
Upvotes: 2