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 with
functools.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