Explain Codes LogoExplain Codes Logo

What does functools.wraps do?

python
decorators
functools
debugging
Anton ShumikhinbyAnton Shumikhin·Aug 3, 2024
TLDR

In a Pythonic nutshell, functools.wraps is a decorator for decorators. It helps in preserving a function's metadata when it's decorated. The function's original name, docstring, and additional metadata can be lost in translation during decoration. The wraps decorator attaches this lost information back to the decorated function.

Example:

from functools import wraps def my_decorator(func): # Just like in the movie Inception, a decorator inside a decorator. Deep! @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @my_decorator def say_hello(): """Prints hello""" print("Hello!") # Checking the function name and docstring print(say_hello.__name__) # 'say_hello' print(say_hello.__doc__) # 'Prints hello'

Safeguarding function signature

Every function in Python has a unique footprint, its signature. This includes its __name__, __doc__, __annotations__, and __module__ attributes. These define the function's identity and its documentation.

Decorators, as their name suggests, add or modify behavior to functions or methods. But they act like a mask, hiding the actual face (signature) of a function. This is where functools.wraps turns the tide. By applying this, we ensure that the function's original signature is maintained.

Debugging made less frightful

The intrinsic property of decorators to hide or overwrite existing function attributes can be your worst nightmare while debugging. functools.wraps is the knight in shining armor here. It ensures the transparency of the original function, making your debugging life significantly less stressful.

Next level usage with libraries

Welcome to the next level of functools.wraps. Libraries like inspect, decopatch and makefun take the functionality of wraps to luxury levels. They allow full preservation of the function signature, not just the basic metadata. This superpower is fundamental for building robust and effective decorator patterns.

Under the hood with functools.wraps

@functools.wraps is actually an alias for the function functools.update_wrapper. This function isn't shy; it loves to copy and update. It performs a deep copy of the wrapper and the wrapped function's attributes, effectively preserving the function's metadata.

More candy for the mind

Here are some more sweet tips to savor:

  • functools.wraps is your best ally for writing maintainable decorators.
  • If you're a fan of tools and IDEs that utilize function metadata (like many of us), functools.wraps is an absolute necessity.
  • Do remember - functools.wraps is not omnipotent. It can't copy dynamic function attributes.
  • Don't shy away from the source code of functools.wraps. It's your friendly neighbourhood manual.