我正在使用以下资源来学习装饰器类:
   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下作为闭合变量。

10-07 21:37