Decorators: count the calls
A decorator is a function that takes a function and returns a new one that
wraps it β adding behavior around the original without touching its body.
The @ syntax is just sugar for f = decorator(f):
def announce(fn):
def wrapper(*args, **kwargs):
print("calling", fn.__name__)
return fn(*args, **kwargs)
return wrapper
@announce
def add(a, b):
return a + b
add(2, 3) # prints "calling add", returns 5
The inner wrapper closes over fn, so it can run extra code and still
forward every argument with *args, **kwargs.
Your task
Write a decorator count_calls(fn) that wraps fn so the wrapper still
returns whatever fn returns, but also exposes a .calls attribute on the
wrapper holding how many times it has been invoked (starting at 0).
@count_calls
def square(n):
return n * n
square(2) # 4
square(5) # 25
square.calls # 2
Hint: inside count_calls, define a wrapper(*args, **kwargs) that bumps a
counter living on the wrapper itself, then forwards to fn. Initialise that
counter to zero after you define wrapper, but before you return it.
Tests
- result preserved
- starts at zero
- counts invocations
- forwards kwargs
β¦ Stuck? Ask for a spark
Sign in or create a free account to use your monthly AI explainer allowance.
$ Console output will appear here.