Say I have a function defined thus:
def inner_func(spam, eggs):
# code
I then want to call a function like this:
outer_func(spam=45, eggs="blah")
Inside outer_func
I want to be able to call inner_func
with exactly the same parameters that were passed into outer_func
.
This can be achieved by writing outer_func
like this:
def outer_func(spam, eggs):
inner_func(spam, eggs)
However, I'd like to be able to change the arguments inner_func
takes, and change the parameters I pass to outer_func
accordingly, but without having to change anything in outer_func
each time.
Is there a (easy) way to do this? Python 3 please.
The double asterisk form of **kwargs is used to pass a keyworded, variable-length argument dictionary to a function. Again, the two asterisks (**) are the important and along with the word kwargs, indicate that there is a dictionary of variable-length keyworded arguments.
**kwargs allows us to pass a variable number of keyword arguments to a Python function. In the function, we use the double-asterisk ( ** ) before the parameter name to denote this type of argument.
Functions can also be called using keyword arguments of the form kwarg=value . During a function call, values passed through arguments need not be in the order of parameters in the function definition.
Looks like you're looking for the *
and **
notations:
def outer_func(*args, **kwargs):
inner_func(*args, **kwargs)
Then you can do outer_func(1, 2, 3, a='x', b='y')
, and outer_func
will call inner_func(1, 2, 3, a='x', b='y')
.
If you only want to allow keyword arguments, drop the *args
.
In a function definition, a parameter marked with *
receives a tuple of all positional arguments that didn't correspond to other declared parameters, and an argument marked with **
receives a dict of all keyword arguments that didn't correspond to other declared parameters.
In a function call, prefixing a sequence (or other iterable) argument with *
unpacks it into separate positional arguments, and prefixing a mapping argument with **
unpacks it into separate keyword arguments.
Not entirely sure I'm getting your drift but you may find functools.wraps
interesting:
@functools.wraps(inner_func)
def outer_func(*args, **kwds):
return inner_func(*args, **kwds)
inspect.signature(outer_func)
# <Signature (spam, eggs)>
Explanation: The "star arguments" collect all the not explicitly specified postional (*args) and keyword (**kwds) arguments that were passed. They can also be used to pass these parameters on; or to manipulate them: args
is a tuple and kwds
is a dict.
Since for example parameter spam
will end up either in args
or kwds
depending on how it was passed, manually parsing star args can be tedious. Here the inspect.Signature
class and in particular its .bind
and .bind_partial
methods are useful.
functools.wraps
is a convenience function/decorator that tweaks many special attributes of the decorated function to make it look like the wrapped function. In particular it copies the name, the signature, the doc string and whatever may be in the wrapped functions __dict__
.
This makes wrapper functions much more user friendly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With