MiddleCodeOccasionalNot answered yet
Write a decorator that times a function
Implement timed, a decorator that prints how long the wrapped call took.
Requirements:
- Forward arbitrary
*args/**kwargsto the wrapped function and return its result. - Preserve the wrapped function's name and docstring.
import functools, time
def timed(func):
# your code here
@timed
def slow():
time.sleep(0.1)
Write the implementation.
Return a closure that records time.perf_counter() before and after the call, forwards *args, **kwargs, and returns the result. Apply @functools.wraps(func) to the wrapper so it keeps the original name and docstring — without wraps, the decorated function loses that metadata.
- ✗Returning the elapsed time instead of the function's result
- ✗Dropping
*args/**kwargs, so the wrapper can't forward arguments - ✗Omitting
functools.wraps, losing the function's name and docstring
- →What exactly does
functools.wrapscopy onto the wrapper? - →How would the decorator change if it had to accept its own argument, like a label?
Contents
Task
Implement the timed decorator that prints the call duration, forwards arguments, and preserves the function's metadata.
Solution
import functools, time
def timed(func):
@functools.wraps(func) # preserves name/docstring
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.perf_counter() - start:.4f}s")
return result
return wrapper
@timed
def slow():
time.sleep(0.1)
Key points
wrapper(*args, **kwargs)forwards any arguments and returns the function's real result.functools.wrapscopies__name__,__doc__, etc. — otherwise they becomewrapper.time.perf_counteris a high-resolution monotonic clock, better thantime.timefor timing.
Contents