๐ Python Decorators Explained with Examples
Decorators are one of Python's most elegant features. They wrap functions to add extra behaviour โ without changing the original function code.
The most common decorator bugs: forgetting @functools.wraps and forgetting to RETURN the wrapper function.
๐ป Code Example:
import time import functools # 1. Basic decorator โ timing a function def timer(func): @functools.wraps(func) # Preserves original function name/docstring def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"{func.__name__} took {end - start:.4f} seconds") return result return wrapper @timer def pynfinity_process(data_size): return sum(range(data_size)) pynfinity_process(1_000_000) # pynfinity_process took 0.04 seconds # 2. Decorator with arguments def retry(max_attempts=3): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): for attempt in range(1, max_attempts + 1): try: return func(*args, **kwargs) except Exception as e: print(f"Attempt {attempt} failed: {e}") raise Exception("All attempts failed") return wrapper return decorator @retry(max_attempts=3) def fetch_data_from_tvk_api(): raise ConnectionError("Server unreachable") # Simulated failure try: fetch_data_from_tvk_api() except Exception as e: print(f"Final error: {e}")
| Concept | Key Takeaway |
|---|---|
| @functools.wraps | Always use โ preserves function metadata |
| Decorator stack | Multiple decorators apply bottom-up: @b @a means a(b(func)) |
| Class decorators | A class with __call__ can also be a decorator |
| Built-in decorators | @property, @staticmethod, @classmethod in Python OOP |
Keep exploring and happy coding! ๐