It is strange that you are not doing anything with *args . Is it possible that the __call__ line is __call__ ?
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__)) return self.func(*args)
Recall that decorator syntax is another way of saying this.
def spam(a, b, c): print(a + b + c) spam = tracer(spam)
therefore, spam becomes an instance of the tracer class and spam is passed to the __init__ method and stored in self.func
Now, when spam is called, you call this instance of the tracer, so the __call__ method is __call__ .
Usually do nothing __call__ wrapper
def __call__(self, *args, **kw): return self.func(*args, **kw)
I don’t know why he didn’t include support for keyword arguments, but ignoring this, you see that there are only two additional lines that are run every time an instance of the tracer is called.
source share