How to Use the Kwargs in Python

by: George El., March 2019, Reading time: 3 minutes

In the previous post we saw how to unpack an iterable using the * operator and how to pass parameters to functions using the * operator. In this post I will show you how to pass parameters to functions using the ** operator and how to combine * and ** together. Please read the previous post first Unpacking in Python and the * operator

Lets assume I have a function that accepts three parameters a,b,c and prints them. I can call this function using a list and unpacking it using *. But I can also call it with unpacking a dictionary to key value pairs. The keys must match the parameters in the function. To unpack the dictionary to key value pairs I use the ** operator.

>>> def func(a,b,c):
...     print(a,b,c)
...
>>> dict1 = {'a':1,'b':2,'c':3}
>>> func(**dict1)
1 2 3

If I try to call with a dictionary that the keys do not match I get an error

>>> dict2 = {'x':1,'b':2,'c':3}
>>> func(**dict2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() got an unexpected keyword argument 'x'

We can combine the * and the ** operators

>>> def func(x,y,z,a,b,c):
...     print(x,y,z,a,b,c)
...
>>> l1 = [1,2,3]
>>> dict1 = {'a':4,'b':5,'c':6}
>>> func(*l1,**dict1)
1 2 3 4 5 6

So * and ** unpack iterables and dictionaries into their elements. But we can also do the reverse

>>> def func(*args, **kwargs):
...     print(args,kwargs)
...
>>> func(*l1,**dict1)
(1, 2, 3) {'a': 4, 'b': 5, 'c': 6}

In the above function we can pass any number of arguments. Arguments that are without a variable are called positional and are stored in args, while arguments with variables are placed in kwargs and are called keyword arguments. For instance:

>>> def func(*args, **kwargs):
...     print(args)
...     print(kwargs)
...
>>> func(1,2,3,4,x=1,y=2)
(1, 2, 3, 4)
{'x': 1, 'y': 2}
>>>

1,2,3,4 are positional arguments, x,y are keyword arguments. There is a rule here. You cannot place positional arguments after keyword arguments. The following will not work.

>>> func(x=1,y=2,1,2,3,4)
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>>

So If I have a function that accepts an ip address, a username and a password to login to a router, I can pass the arguments from a dictionary like in the following.

>>> def func_login(ip, username='cisco', password='cisco'):
...     print(ip, username, password)
...
>>> router1 = { 'ip':'192.168.1.1','username':'user01','password':'pass01' }
>>> func_login(**router1)
192.168.1.1 user01 pass01
>>> router2={'ip':'192.168.2.2'}
>>> func_login(**router2)
192.168.2.2 cisco cisco

I also specified a default value for username and password. If they are not specified, the defaults will be used. Finally please note that keyword arguments do not have to be in order.

>>> router3={'password':'pass02','username':'user02','ip':'192.168.2.3'}
>>> func_login(**router3)
192.168.2.3 user02 pass02
comments powered by Disqus