装饰器类无法调用'NoneType'对象

时间:2018-10-12 16:39:35

标签: python class decorator python-decorators

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

1 个答案:

答案 0 :(得分:2)

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下作为封闭变量。