Reputation: 1019
I'm learning about decorator classes using this resource:
http://book.pythontips.com/en/latest/decorators.html#decorator-classes
The presented class is basically this:
class logit(object):
def __init__(self, logfile='out.log'):
self.logfile = logfile
def __call__(self, func):
log_string = func.__name__ + " was called"
print(log_string)
# Open the logfile and append
with open(self.logfile, 'a') as opened_file:
# Now we log to the specified logfile
opened_file.write(log_string + '\n')
# Now, send a notification
self.notify()
def notify(self):
# logit only logs, no more
pass
and the call:
@logit()
def myfunc1():
pass
myfunc1()
I get an error:
>>> myfunc1()
[...]
TypeError: 'NoneType' object is not callable
Upvotes: 2
Views: 1512
Reputation: 78700
logit.__call__
does return None
, and you are doing myfunc1 = logit()(myfunc1)
via decoration. myfunc
is now None
.
As far as I understand, you want to log each call of the decorated function. In this case, __call__
must build a new function and return
it.
Something like
def __call__(self, func):
def new_func(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# Open the logfile and append
with open(self.logfile, 'a') as opened_file:
# Now we log to the specified logfile
opened_file.write(log_string + '\n')
# Now, send a notification
self.notify()
# execute func
return func(*args, **kwargs)
return new_func
Now
@logit()
def myfunc1():
pass
does
myfunc1 = logit()(myfunc1)
i.e. it reassigns the name myfunc1
to the new function built in __call__
. This new function does the logging-logic and then executes the old myfunc1
which it still holds onto under the name func
as a closure variable.
Upvotes: 2