The special syntax *args in function definitions in python is used to pass a variable number of arguments to a function. It is used to pass a non-key worded, variable-length argument list. The syntax is to use the symbol * to take in a variable number of arguments; by convention, it is often used with the word args.
You can send any data types of argument to a function (string, number, list, dictionary etc.), and it will be treated as the same data type inside the function.
The ** unpacking operator can be used to pass kwargs from one function to another function's kwargs. Consider this code: (newlines don't seem to be allowed in comments) def a(**kw): print(kw) , and def b(**kw): a(kw) .
To expand a little on the other answers:
In the line:
def wrapper(func, *args):
The * next to args
means "take the rest of the parameters given and put them in a list called args
".
In the line:
func(*args)
The * next to args
here means "take this list called args and 'unwrap' it into the rest of the parameters.
So you can do the following:
def wrapper1(func, *args): # with star
func(*args)
def wrapper2(func, args): # without star
func(*args)
def func2(x, y, z):
print x+y+z
wrapper1(func2, 1, 2, 3)
wrapper2(func2, [1, 2, 3])
In wrapper2
, the list is passed explicitly, but in both wrappers args
contains the list [1,2,3]
.
The simpliest way to wrap a function
func(*args, **kwargs)
... is to manually write a wrapper that would call func() inside itself:
def wrapper(*args, **kwargs):
# do something before
try:
return func(*a, **kwargs)
finally:
# do something after
In Python function is an object, so you can pass it's name as an argument of another function and return it. You can also write a wrapper generator for any function anyFunc():
def wrapperGenerator(anyFunc, *args, **kwargs):
def wrapper(*args, **kwargs):
try:
# do something before
return anyFunc(*args, **kwargs)
finally:
#do something after
return wrapper
Please also note that in Python when you don't know or don't want to name all the arguments of a function, you can refer to a tuple of arguments, which is denoted by its name, preceded by an asterisk in the parentheses after the function name:
*args
For example you can define a function that would take any number of arguments:
def testFunc(*args):
print args # prints the tuple of arguments
Python provides for even further manipulation on function arguments. You can allow a function to take keyword arguments. Within the function body the keyword arguments are held in a dictionary. In the parentheses after the function name this dictionary is denoted by two asterisks followed by the name of the dictionary:
**kwargs
A similar example that prints the keyword arguments dictionary:
def testFunc(**kwargs):
print kwargs # prints the dictionary of keyword arguments
You can use *args and **kwargs syntax for variable length arguments.
What do *args and **kwargs mean?
And from the official python tutorial
http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions
The literal answer to your question (to do exactly what you asked, changing only the wrapper, not the functions or the function calls) is simply to alter the line
func(args)
to read
func(*args)
This tells Python to take the list given (in this case, args
) and pass its contents to the function as positional arguments.
This trick works on both "sides" of the function call, so a function defined like this:
def func2(*args):
return sum(args)
would be able to accept as many positional arguments as you throw at it, and place them all into a list called args
.
I hope this helps to clarify things a little. Note that this is all possible with dicts/keyword arguments as well, using **
instead of *
.
You need to use arguments unpacking..
def wrapper(func, *args):
func(*args)
def func1(x):
print(x)
def func2(x, y, z):
print x+y+z
wrapper(func1, 1)
wrapper(func2, 1, 2, 3)
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