Access to the Original Function in Decorators – Python 2026 Best Practices
When you apply a decorator, the original function is replaced by the wrapper. However, you can still access the original function using the __wrapped__ attribute. This is very useful for introspection, testing, and advanced decorator patterns.
TL;DR — Key Points 2026
- Every decorated function has a
__wrapped__attribute pointing to the original function - This is automatically added when you use
@wraps - Useful for calling the original function directly, testing, and debugging
- Works with stacked (multiple) decorators too
1. Basic Access to Original Function
from functools import wraps
import time
def timer(func):
@wraps(func)
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(n: int):
"""Heavy calculation function."""
return sum(i ** 2 for i in range(n))
# Accessing the original function
original_calculate = calculate.__wrapped__
print(calculate.__name__) # "calculate"
print(original_calculate.__name__) # "calculate"
print(calculate.__wrapped__ is original_calculate) # True
# You can call the original directly (without timing)
result = original_calculate(10000)
2. With Multiple (Stacked) Decorators
@timer
@log_call
def process_data(data):
return [x * 2 for x in data]
# Access the original function (bypassing all decorators)
original = process_data.__wrapped__.__wrapped__ # Go through the stack
# Or use a loop to unwrap all decorators
def unwrap(func):
while hasattr(func, '__wrapped__'):
func = func.__wrapped__
return func
original_process = unwrap(process_data)
3. Best Practices in 2026
- Use
__wrapped__when you need to bypass decorators (e.g., in tests) - Always apply
@wrapsso__wrapped__is available - For deep decorator stacks, create a helper function to unwrap
- Be careful not to call
__wrapped__in production code unless necessary - Document when you intentionally access the original function
Conclusion
Access to the original function via __wrapped__ is an important feature when working with decorators. In 2026, professional Python developers know how to use this attribute for testing, debugging, and advanced decorator patterns while keeping their code clean and maintainable.
Next steps:
- Try accessing
__wrapped__on your existing decorated functions - Related articles: Decorators in Python 2026 • Decorators and Metadata Preservation in Python 2026 • Writing Functions in Python 2026