logo

Preserving Function Metadata

When you decorate a function, it gets replaced by wrapper. This loses the original name and docstring:

@my_decorator
def add(a, b):
    """Add two numbers."""
    return a + b

print(add.__name__)  # "wrapper" - not "add"!
print(add.__doc__)   # None - docstring is lost!

Fix this with @functools.wraps:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

Now the decorated function keeps its identity:

print(add.__name__)  # "add"
print(add.__doc__)   # "Add two numbers."

Always use @wraps in your decorators. It's essential for debugging, documentation, and introspection tools.

I cover functools.wraps in my Python Decorators course.