1.13 args and kwargs
Contents
Note
Click here to download the full example code or to run this example in your browser via Binder
1.13 args and kwargs#
Important
This lesson is still under development.
*args
#
We have learned about function that they can take one or more input arguments. If we want our function to have variable number of input arguments, one way to do this is to put args inside ``()`` during function definition. This will allow us to have multiple **unnamed* input arguments.
def add_nums(*args):
print(type(args), len(args), args)
add_nums(5, 12.0)
<class 'tuple'> 2 (5, 12.0)
*args
converts all the unnamed input arguments to the function add_nums
into tuple. Inside the above function, the unnamed input arguments 5 and 12 become (5, 12) tuple.
<class 'tuple'> 1 ([2, 3, 4],)
Inside the function add_nums, the input argument [2,3,4] which is a list, is taken as ([2,3,4],) which is tuple.
def do_add(*args):
print(len(args), 'in do_add')
for arg in args:
print(arg)
return
def add_nums(*args):
# we get a tuple i.e. (12,14)
print(len(args), 'in add_nums')
# we pass the tuple (12,14) as input argument and NOT 12,14 as two input arguments
return do_add(args)
add_nums(12, 14)
2 in add_nums
1 in do_add
(12, 14)
2 in add_nums
2 in do_add
26
Above: add_nums and do_add are called with exactly same kind of input arguments.
Following is example of misplaced return statement
2 in add_nums
3 in do_add
2
2 in add_nums
2 in do_add
31
a
is the positional argument which takes 5, while while 12 and 14 are given
as tuple to the function
1 5 12
if the list l contains more than 3 elements, passing it will raise error
# uncomment following line
# l = [1, 5, 12, 3]
# add_nums(*l)
Although we can vary the number of arguments by using *args but we can not know the name of input args.
**kwargs
#
<class 'dict'>
def add_nums(**dictionary):
print(type(dictionary), len(dictionary))
add_nums(a=5, b=12)
<class 'dict'> 2
def add_nums(**kwargs):
print(type(kwargs))
a = 5
b = 12
dictionary = {'a': a, 'b': b}
add_nums(a,b) is invalid, add_nums(dictionary) is invalid as well
add_nums(**dictionary)
<class 'dict'>
def add_nums(**kwargs):
x = kwargs['a']
y = kwargs['b']
return x + y
a = 5
b = 12
dictionary = {'a': a, 'b': b}
add_nums(**dictionary)
17
Omitting **
on both sides also serves the purpose.
However, if we omit **
in function definition, it would mean that
function requires an input argument named kwargs
. If we ommit **
when
calling the function it means that we are giving a dicionary as it is as input argument.
def add_nums(kwargs):
x = kwargs['a']
y = kwargs['b']
return x + y
a = 5
b = 12
dictionary = {'a': a, 'b': b}
add_nums(dictionary)
17
<class 'int'>
26
def add_nums(xx, **kwargs):
x = kwargs['a']
y = kwargs['b']
return xx + x + y
dictionary = {'a': 5, 'b': 12}
add_nums(1, **dictionary)
18
xx
is assigned the value of 1 when the function add_nums is called.
We can put extra named arguments separately along with **kwargs.
def add_nums(xx=1, **kwargs):
_sum = 0.0
for key, val in kwargs.items():
_sum += val
return _sum
dictionary = {'a': 5, 'b': 12}
add_nums(**dictionary)
17.0
The value of xx which is 1 is not added in the final answer.
32.0
now kwargs contained a, b, c and d only. The above code can also be written as following.
def add_nums(xx=1, yy=12, zz=14, **kwargs):
_sum = 0.0
for key, val in kwargs.items():
_sum += val
return _sum
additional_args = {
"a": 1,
"b": 5,
"c": 12,
"d": 14,
}
add_nums(xx=114, yy=313, zz=7, **additional_args)
32.0
A misplaced return can be a cause of many headachs, as in following case.
def add_nums(xx=1, yy=12, zz=14,
**kwargs):
# if number of arguments are large, it is totally fine to go on
# second line without any probelm
_sum = 0.0
for key, val in kwargs.items():
_sum += val
return _sum
additional_args = {
"a": 114,
"b": 5,
"c": 12,
"d": 14,
}
add_nums(xx=114, yy=313, zz=7, **additional_args)
114.0
Above, the function add_nums finishs execution just after first iteration of for loop.
def cook_lunch_with_bread(raw_food):
print('prepare lunch with break')
def cook_lunch_without_bread(raw_food):
print('prepare lunch with {}, {} and without bread'.format(*raw_food.keys()))
def lunch(**raw_food):
if 'bread' in raw_food:
cook_lunch_with_bread(raw_food)
else:
cook_lunch_without_bread(raw_food)
lunch(rice='2', milk=1)
prepare lunch with rice, milk and without bread
We can predefine/fix the number of positional arguments and keyword arguments that a function must take. Following code allows only 3 positional keyword arguments and 2 keyword arguments.
we can not do add_num(2,3,4, 12, 14), as this would mean 5 positional arguments instead of 3.
add_nums(2, 3, 4, d=12, e=14)
2 3 4
0 0
5
add_nums(2, 3, 4, 5)
2 0
14
4 and 5 goes to args
add_nums(2, 3, 4, 5, 6, d=5, e=12)
3 2
37
4, 5, 6 goes to args and d and e goes to kwargs
We can replace the words args and kwargs with any other variable name. It is just a convention to use the word args for unnamed arguments and the word kwargs for keyword arguments. The actual packing and unpacking is done by `*` and `**` in python. For example, the above function can also be written as below
def add_nums(one, five, *unnamed, **named):
_sum = one + five
print(len(unnamed), len(named))
for arg in unnamed:
_sum += arg
for key, val in named.items():
_sum += val
return _sum
add_nums(1, 5, 12, infallibles=14, messangers=313)
1 2
345
Total running time of the script: ( 0 minutes 0.012 seconds)