PyForge ยท Python practice library
All topics

Topic 16 of 17

Decorators

Wrap functions to add cross-cutting behavior cleanly.

Higher-order functions
@decorator syntax
functools.wraps
Parameterized decorators

Intermediate

1 program

Program 1

Basic decorator

Intermediate

Add behavior before and after a function call.

python
def log(fn):
    def wrapper(*args, **kwargs):
        print(f"Calling {fn.__name__}")
        result = fn(*args, **kwargs)
        print(f"Done {fn.__name__}")
        return result
    return wrapper

@log
def add(a, b):
    return a + b

print(add(2, 3))

Advanced

2 programs

Program 1

Timing decorator

Advanced

Measure execution time.

python
import time
from functools import wraps

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

@timed
def slow():
    time.sleep(0.2)

slow()

Program 2

Decorator with arguments

Advanced

Repeat a function N times.

python
def repeat(times):
    def deco(fn):
        def wrapper(*a, **kw):
            for _ in range(times):
                fn(*a, **kw)
        return wrapper
    return deco

@repeat(3)
def hello(name):
    print("Hi", name)

hello("Ada")