Before starting, please note that Python's syntax includes just *
(asterisk) and **
(double asterisk), and the words args and kwargs are just conventions and not imposed by language. So, you can use any other words instead of args and kwargs.
Normally, the functions we make in Python can take a fixed number of arguments. For example, a function foo(a, b)
can take only two arguments while a function foo(a, b, c)
can take only three arguments. But in real life, we come across situations where different numbers of arguments need to passed in each function call. For example, a simple function to add numbers (let's say sum_numbers) can't be made to take a fixed number of arguments. We should have the flexibility to call the function with any number of arguments, i.e., sum_numbers(2, 3)
sum_numbers(2, 3, 4)
, etc. These kind of situations are handled with *
and **
.
*args
*
is used to handle situations where the number of arguments is not fixed, and also the name of the arguments is not important. So, let's make our first function with *args
.
def foo(*args):
print (args)
print (type(args))
foo(1,2)
foo(1,2,3)
Output
(1, 2)
<class 'tuple'>
(1, 2, 3)
<class 'tuple'>
You can see that we have passed a different number of arguments in the above function foo
and *
(or *args
) packed them into a tuple. Now, let's make a function to add numbers.
def sum_numbers(*args):
s = 0
for i in args:
s = s+i
print (s)
sum_numbers(1,2)
sum_numbers(1,2,3)
Output
3
6
*args as argument
In previous examples, we have used *args
as the parameter of the functions. We can also use *args
as an argument and pass it to the function.
def foo(a, b, c):
print (a)
print (b)
print (c)
args = [1, 2, 3]
foo(*args)
Output
1
2
3
You can see that, we have made an iterable (a list in this case) and used *args
to pass it to the function foo
and *
unpacked the iterable args.
**kwargs
*
is also used to handle situations where the number of arguments is not fixed but instead of making a tuple, *
makes a dictionary. So, we can use *
for key-worded arguments, e.g., foo(a = 1, b = 2)
. As stated, *
makes a dictionary, so foo(a = 1, b = 2)
will be packed to {'a' : 1, 'b' : 2}
. Let's look at an example for this.
def foo(**kwargs):
print (kwargs)
print (type(kwargs))
foo(a = 1, b = 2, c = "Hello", d = "BlogsDope")
foo(a = 1, b = 2)
Output
{'a': 1, 'b': 2, 'c': 'Hello', 'd': 'BlogsDope'}
<class 'dict'>
{'a': 1, 'b': 2}
<class 'dict'>
def foo(**kwargs):
for i in kwargs:
print (kwargs[i])
foo(a = 1, b = 2)
Output
1
2
**kwargs as argument
Similar to *args
, we can also **kwargs
as an argument to a function.
def foo(a, b, c):
print (a)
print (b)
print (c)
kwargs = {'a':1,'b':2,'c':3}
foo(**kwargs)
Output
1
2
3
Using *args and **kwargs together
While using *args
or **kwargs
with other parameters or using them together, one should keep in mind that the arguments should follow the given order:
- Formal arguments
- *args
- keyword arguments
- **kwargs
Some examples are given to illustrate using them together.
def foo(*args, **kwargs):
print (args)
print (kwargs)
foo(1, 2, a = 5, b = 6)
Output
(1, 2)
{'a': 5, 'b': 6}
def foo(a, b, *args, c = 5, d = 9, **kwargs):
print (args)
print (kwargs)
print(a)
print(b)
print(c)
print(d)
foo(1, 2, 3, 4, 5, 6, 7, 8, e=13, f=14, g = 15, h = 16)
Output
(3, 4, 5, 6, 7, 8)
{'e': 13, 'f': 14, 'g': 15, 'h': 16}
1
2
5
9