该代码取自Mark Lutz的Learning Python第4版
class tracer:
def __init__(self, func):
self.calls = 0
self.func = func
def __call__(self, *args):
self.calls += 1
print('call %s to %s' % (self.calls, self.func.__name__))
self.func(*args)
@tracer
def spam(a, b, c):
print(a + b + c)
spam(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
此外,当我运行此代码时,它也不会打印1,2,3的总和,但在书中,它表明它确实如此!我对整个代码感到头疼.我不知道这里发生了什么.
这里发生的是功能的主体正在被替换.像这样的装饰师
@tracer
def spam(...)
...
Run Code Online (Sandbox Code Playgroud)
相当于:
def spam(...)
...
spam = tracer(spam)
Run Code Online (Sandbox Code Playgroud)
现在,tracer(spam)返回存储tracer原始定义的类的实例spamself.func
class tracer:
def __init__(self, func): #tracer(spam), func is assigned spam
self.calls = 0
self.func = func
Run Code Online (Sandbox Code Playgroud)
现在,当您调用spam(实际上是其实例tracer)时,您将调用类中__call__定义的方法tracer:
def __call__(self, *args):
self.calls += 1
print('call %s to %s' % (self.calls, self.func.__name__))
Run Code Online (Sandbox Code Playgroud)
所以在本质中,这种__call__方法已经覆盖了原始定义的体spam.要使主体执行,您需要调用存储在tracer类实例中的函数,如下所示:
def __call__(self, *args):
self.calls += 1
print('call %s to %s' % (self.calls, self.func.__name__))
self.func(*args)
Run Code Online (Sandbox Code Playgroud)
导致
>>>
call 1 to spam
6
Run Code Online (Sandbox Code Playgroud)