MiddleCodeOccasionalNot answered yet
Decorator that repeats a call N times and reports total time
Write repeat(reps), a parameterized decorator that runs the wrapped function reps times, prints the total elapsed time, and returns the last call's result.
Requirements:
- Take
repsas a decorator argument:@repeat(3). - Forward
*args/**kwargs; preserve the wrapped function's metadata.
def repeat(reps):
# your code here
Write the implementation.
Use three nested levels: repeat(reps) captures the count and returns a decorator; that decorator takes func and returns a @wraps(func) wrapper. The wrapper records time.perf_counter(), runs func reps times (keeping the last result), prints the elapsed total, and returns that result. The argument layer is what @repeat(3) requires; @wraps preserves the name and docstring.
- ✗Using two levels and failing to accept the
repsargument cleanly - ✗Resetting the timer inside the loop instead of timing the whole run
- ✗Omitting
@wraps, losing the function's name and docstring
- →Why does taking a decorator argument require a third nesting level?
- →What breaks for callers if you omit
@wrapson the wrapper?
Contents
Task
Implement repeat(reps): run the function reps times, print the total time, and return the last call's result.
Solution
import time
from functools import wraps
def repeat(reps):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = None
for _ in range(reps):
result = func(*args, **kwargs)
print(f"{reps} repetitions in {time.perf_counter() - start} secs")
return result
return wrapper
return decorator
Key points
- Three levels: factory
repeat(reps)→ decoratordecorator(func)→wrapper. - The timer starts once around the whole loop, not inside it.
@wraps(func)preserves the name and docstring; the result is from the last call.
Contents