Lesson 37 / 47

Practical Decorators

Common real-world uses: timing, logging, and decorators that take arguments.

Timing a function

A timing decorator measures how long a function takes — useful for spotting slow code without touching its body.

import time

def timed(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} took {elapsed:.4f}s")
        return result
    return wrapper

@timed
def slow_add(a, b):
    time.sleep(0.1)
    return a + b

slow_add(2, 3)

Decorators with arguments

To make a decorator take its own arguments (like @retry(times=3)), wrap it in one more outer function layer.