Decorators and Metadata Preservation in Python 2026 – Best Practices
When you apply a decorator to a function, Python replaces the original function with the wrapper returned by the decorator. This causes the loss of important metadata such as `__name__`, `__doc__`, `__module__`, and function signature. In 2026, preserving metadata is considered mandatory for professional code.
TL;DR — Key Rule in 2026
- Always use
@wraps(func)fromfunctoolsin every decorator - This preserves the original function’s name, docstring, signature, and other metadata
- Without
wraps, tools like IDEs, debuggers, and documentation generators break
1. The Problem Without Metadata Preservation
def bad_timer(func):
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
@bad_timer
def calculate():
"""This is an important calculation function."""
return 42
print(calculate.__name__) # "wrapper" ← Broken!
print(calculate.__doc__) # None ← Docstring lost!
2. Correct Way – Using @wraps (2026 Standard)
from functools import wraps
import time
def timer(func):
"""Decorator that measures execution time and preserves metadata."""
@wraps(func) # ← This is the key line
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"⏱️ {func.__name__}() took {elapsed:.6f} seconds")
return result
return wrapper
@timer
def calculate():
"""This is an important calculation function."""
return 42
print(calculate.__name__) # "calculate" ✓
print(calculate.__doc__) # "This is an important calculation function." ✓
help(calculate) # Shows original signature and docstring
3. Best Practices for Metadata in 2026
- Always use
@wraps(func)in every decorator you write - Place
@wrapson the inner wrapper function - Use it even for simple decorators
- For advanced cases, consider the
wraptlibrary - This ensures compatibility with IDEs, type checkers, and documentation tools
Conclusion
Preserving metadata with functools.wraps is no longer optional — it is a required best practice in 2026. Forgetting to use @wraps breaks introspection, debugging, and documentation. Always include it in every decorator you create.
Next steps:
- Go through all your custom decorators and add
@wraps(func)where missing - Related articles: Decorators in Python 2026 • Writing Functions in Python 2026