The double_args decorator is a practical example of a parameterized decorator in Python — it takes a function, wraps it to double all positional and keyword arguments (assuming they are numbers), and calls the original function with those doubled values. This demonstrates higher-order functions, argument manipulation, and the power of decorators to transparently modify behavior without changing the decorated function’s source code. In 2026, decorators like this are commonly used for input scaling/normalization, testing edge cases, retry logic, logging argument transformations, or adapting legacy functions in data pipelines, ML workflows, and production systems — especially when combined with type hints, error handling, and pandas/Polars transformations.
Here’s a complete, practical guide to the double_args decorator: how it works, implementation details, usage examples, handling non-numeric arguments, real-world patterns, and modern best practices with type hints, error handling, performance, and pandas/Polars integration.
Implementation — the decorator uses *args and **kwargs to accept any arguments, doubles them (via list/dict comprehensions), and passes the new versions to the original function.
def double_args(func):
"""Decorator that doubles all numeric arguments before calling the function."""
def wrapper(*args, **kwargs):
# Double positional arguments (assume they are numbers)
new_args = [2 * arg if isinstance(arg, (int, float)) else arg for arg in args]
# Double keyword arguments (assume values are numbers)
new_kwargs = {k: 2 * v if isinstance(v, (int, float)) else v for k, v in kwargs.items()}
# Call original function with doubled args
return func(*new_args, **new_kwargs)
return wrapper
Basic usage — decorate a function to automatically double its numeric inputs.
@double_args
def add_numbers(a: int, b: int, c: int = 0) -> int:
return a + b + c
result = add_numbers(1, 2, c=3)
print(result) # 12 (doubled: 2 + 4 + 6)
Real-world pattern: input scaling in pandas/Polars pipelines — use double_args (or similar) to normalize/test with scaled inputs without modifying core functions.
import pandas as pd
@double_args
def compute_metrics(df: pd.DataFrame, factor: float = 1.0) -> dict:
"""Example metric function that gets doubled inputs."""
return {
'mean_sales': df['sales'].mean() * factor,
'total_visits': df['visits'].sum() * factor
}
df = pd.DataFrame({'sales': [100, 200], 'visits': [10, 20]})
metrics = compute_metrics(df, factor=1.5)
print(metrics)
# {'mean_sales': 450.0, 'total_visits': 90.0} (doubled args applied)
Best practices make double_args-style decorators safe, readable, and performant. Use type hints — func: Callable[..., Any] — and consider generics for argument/return types. Handle non-numeric arguments gracefully — skip doubling or raise informative errors. Modern tip: use Polars for high-performance transformations — decorate Polars expressions or lazy frames for input scaling/normalization. Add @wraps(func) — preserves name, docstring, annotations. Use *args, **kwargs — makes decorator generic. Return the wrapped result — chainable decorators. Use contextlib.ContextDecorator — class-based decorators that work as context managers. Test decorators independently — wrap dummy functions and assert behavior. Combine with tenacity — retry decorators for transient errors. Use logging inside decorators — centralize logging without cluttering functions. Avoid decorators on generators — can break iteration; use wrappers carefully. Stack decorators thoughtfully — order matters (@double_args @timer vs @timer @double_args). Use functools.partial — pre-bind parameters for reusable decorator instances.
The double_args decorator wraps functions to double numeric arguments — a clear example of argument manipulation via decorators. In 2026, use type hints, @wraps, generic *args/**kwargs, Polars for scalable pipelines, and test thoroughly. Master this pattern, and you’ll write flexible, reusable decorators that transparently enhance functions for scaling, testing, logging, and more.
Next time you need to transform function inputs transparently — write a decorator like double_args. It’s Python’s cleanest way to say: “Double the inputs — without touching the original function.”