*args and **kwargs - Collecting and Unpacking Arguments
Putting *args and/or **kwargs as the last items in our function definition's argument list allows that function to accept an arbitrary number of anonymous and/or keyword arguments.
Those arguments are called Keyword Arguments. Actually, they are place holders for multiple arguments, and they are useful especially when we need to pass a different number of arguments each time we call the function.
Those arguments are called Keyword Arguments. Actually, they are place holders for multiple arguments, and they are useful especially when we need to pass a different number of arguments each time we call the function.
We may want to use *args when we're not sure how many arguments might be passed to our function, i.e. it allows us to pass an arbitrary number of arguments to our function.
Collecting arguments
>>> def f(*args):
print(args)
>>> f()
()
>>> f(10)
(10,)
>>> f(10, 20, 30)
(10, 20, 30)
When the f() is called, Python collects all the positional arguments into a new tuple and assigns the variable args to that tuple. Since it is a normal tuple object, it can be indexed:
>>> def print_all(*args):
for x in enumerate(args):
print x
>>> print_all('A','b','b','a')
(0, 'A')
(1, 'b')
(2, 'b')
(3, 'a')
The ** is similar but it only works for keyword arguments. In other words, it collects them into a new dictionary. Actually, ** allows us to convert from keywords to dictionaries:
>>> def f(**kargs):
print(kargs)
>>> f()
{}
>>> f(a=10, b=20)
{'a': 10, 'b': 20}
The keyword arguments is a special name=value syntax in function calls that specifies passing by name. It is often used to provide configuration options.
>>> def kargs_function(**kargs):
for k,v in kargs.items():
print (k,v)
>>>kargs_function(**{'uno':'one','dos':'two','tres':'three'})
('dos', 'two')
('tres', 'three')
('uno', 'one')
>>>
>>> kargs_function(dos='two', tres='three', uno='one')
('dos', 'two')
('tres', 'three')
('uno', 'one')
>>>
Unpacking arguments
We can use the * or ** when we call a function. In other words, it unpacks a collection of arguments, rather than constructing a collection of arguments. In the following example, we pass five arguments to a function in a tuple and let Python unpack them into individual arguments:
>>> def f(a, b, c, d, e):
print(a, b, c, d, e)
>>> args = (10, 20)
>>> args += (30, 40, 50))
>>> f(*args)
10 20 30 40 50
In the same way, the ** in a function call unpacks a dictionary of key/value pairs into separate keyword arguments:
>>> kargs = {'a':10, 'b':20, 'c':30}
>>> kargs['d']=40
>>> kargs['e']=50
>>> f(**kargs)
10 20 30 40 50
Also, with various combinations:
>>> f(*(10, 20), **{'d':40, 'e':50, 'c':30})
10 20 30 40 50
>>> f(10, *(20, 30), **{'d':40, 'e':50})
10 20 30 40 50
>>> f(10, c = 30, *(20,), **{'d':40, 'e':50})
10 20 30 40 50
>>> f(10, *(20,30), d=40, e=50)
10 20 30 40 50
>>> f(10, *(20,), c=30, **{'d':40, 'e':50})
10 20 30 40 50
Arbitrary function
In the code below, we support any function with any arguments by passing along whatever arguments that were sent in:
>>> def A_function(f, *args, **kargs):
return f(*args, **kargs)
>>> def f(a, b, c, d, e):
return a*b*c*d*e
>>> print(A_function(f, 10, 20, c=30, d=40, e=50))
12000000
When the code is run, arguments are collected by the A_function.
apply() - deprecated
f(*args, **kargs) # newer call syntax: f(*sequence, **dict)
apply(f, args, kargs) # deprecated built-in: apply(f, sequence, dict)
The following function accepts any number of positional or keyword arguments:
>>> def echo(*args, **kargs):
print(args, kargs)
>>> echo(10, 20, a=30, b=40)
(10, 20) {'a': 30, 'b': 40}
If we use the apply():
>>> args = (10, 20)
>>> kargs = {'a':30, 'b':40}
>>> def echo(*args, **kargs):
print(args, kargs)
>>> apply(echo, args, kargs)
((10, 20), {'a': 30, 'b': 40})
>>> echo(*args, **kargs)
((10, 20), {'a': 30, 'b': 40})
Comments
Post a Comment