Especially in function decorators, you often create and return a function that wraps the modifying function you receive as an argument, but sometimes you want the signature of the wrapping function to be the same as the wrapped function. Starting with Python 3.4, this implementation is possible using a decorator called wraps provided by the standard library functools.
In the example below, the funny_function modified with the decorator ʻargs_as_ints (ie the wrappermodified withfunctools.wraps) has the same signature as the modified function funny_function, but all Convert the argument to ʻint and do the same calculation for the original function.
python
# Source: https://stackoverflow.com/questions/147816/preserving-signatures-of-decorated-functions
import functools
def args_as_ints(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return func(*args, **kwargs)
return wrapper
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y + 2*z"""
return x*y + 2*z
After being qualified, the funny_function has a member called __wrapped__, which holds the original function.
Use the standard library inspect to find out the signature of a function. You can use the signature function provided by inspect to retrieve the function's signature as aSignature object. The following code ensures that the funny_function signature is the same before and after qualification.
python
>>> from inspect import signature
>>> str(signature(funny_function))
'(x, y, z=3)'
>>> signature(funny_function) == signature(funny_function.__wrapped__)
True
Recommended Posts