首页 > 解决方案 > 'NoneType' 对象不能用装饰器类调用

问题描述

我正在学习使用此资源的装饰器类: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

标签: pythonclassdecoratorpython-decorators

解决方案


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作为闭包变量保留的旧函数。


推荐阅读