def add(a, b): return a + b
print(power.) # power (not wrapper) print(power. doc ) # Raise base to exponent 6. Decorators with arguments (nested factory) def repeat(times): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): for _ in range(times): result = func(*args, **kwargs) return result return wrapper return decorator
square(3) # Call 1 square(4) # Call 2 print(square.calls) # 2 import time
add = logger(add) # manual decoration print(add(3, 5)) @logger def multiply(a, b): return a * b
multiply(4, 7) from functools import wraps
@debug def power(base, exp=2): """Raise base to exponent""" return base ** exp
def retry(max_attempts=3, delay=1, backoff=2): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): attempts = 0 current_delay = delay while attempts < max_attempts: try: return func(*args, **kwargs) except Exception as e: attempts += 1 if attempts == max_attempts: raise print(f"Attempt {attempts} failed: {e}. Retrying in {current_delay}s") time.sleep(current_delay) current_delay *= backoff return wrapper return decorator