我正在使用以下资源来学习装饰器类:
http://book.pythontips.com/en/latest/decorators.html#decorator-classes
所呈现的类基本上是这样的:
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
并致电:
@logit()
def myfunc1():
pass
myfunc1()
我收到一个错误:
>>> myfunc1()
[...]
TypeError: 'NoneType' object is not callable
最佳答案
logit.__call__
确实返回None
,并且您正在通过装饰进行myfunc1 = logit()(myfunc1)
。 myfunc
现在是None
。
据我了解,您想记录装饰函数的每个调用。在这种情况下,__call__
必须构建一个新函数并return
。
就像是
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
现在
@logit()
def myfunc1():
pass
确实
myfunc1 = logit()(myfunc1)
即它将名称
myfunc1
重新分配给内置在__call__
中的新功能。这个新函数执行日志记录逻辑,然后执行旧的myfunc1
并将其保留在名称func
下作为闭合变量。