- Published on
What are *args and **kwargs in Python
- Authors
- Name
- Bishal Sarangkoti
- @BishalSarang
In this post, I'm going to talk about *args and **kwargs in Python which is a useful concept while handling multiple arguments.
They are called *args
and **kwargs
in Python which allows the function to accept optional arguments(positional
and keyword
). Let’s see with an example. At first, let’s make a simple function that accepts a single argument, first_name
.
>>> def person(first_name):
... print(first_name)
>>> person("Ram")
Ram
>>> person()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() missing 1 required positional argument: 'first_name'
What we can see is first_name
is a compulsory argument. So, it is not possible to call the function without arguments. Now, what we are going to do is make a function that accepts first_name
as compulsory arguments followed by last_name
as an optional argument. One way to do this would be
>>> def person(first_name, last_name=""):
... print(first_name, last_name)
>>> person("Ram") # Called with 1 argument
Ram
>>> person("Ram", "Shrestha") # Called with 2 arguments
Ram Shrestha
So far everything is going well. But now we want to scale the same function to accept first_name
(compulsory) and last_name
and middle_name
as positional arguments. One simple trick is to add another argument middle_name.
>>> def person(first_name, last_name="", middle_name=""):
... print(first_name, middle_name, last_name)
But there is a more concise way to scale the function to accept multiple optional arguments called *args
in Python.
1. *args
*args collects extra positional arguments as a tuple
The idea is simple. We modify our function definition as:
>>> def person(first_name, *args):
... print(first_name, end = " ")
... for names in reversed(args):
... print(names, end=" ")
... print()
>>> # Accepts single argument
>>> person("Ram")
Ram
>>> # Accepts 2 arguments
>>> person("Ram", "Chhetri")
Ram Chhetri
>>> # Accepts 3 arguments
>>> person("Ram", "Chhetri", "Lal")
Ram Lal Chhetri
>>> person("Ram", "Chhetri", "Lal", "Krishna")
Ram Krishna Lal Chhetri
We can see that now our function can accept first_name
followed by last_name
, middle_name
as optional positional arguments. To see if args
is indeed a tuple you can add
print(type(args))
inside of function definition Let’s see another example:
Task 1: Write a function to add N integers which are passed as arguments ( N >= 1) Let’s do it for 1 integer
>>> def add(a):
... return a
>>> add(8)
8
Nothing complicated. Now do it for 2 integers
>>> def add(a, b):
... return a + b
>>> add(8, 2)
10
>>> add(8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'b'
Notice?? We lost the compatibility for 1 argument. This is where *args
comes handy:
>>> def add(a, *args):
... sum = a
... print(type(args))
... for num in args:
... sum += num
... return sum
>>> add(8)
8
>> add(8, 2)
10
>> add(8, 2, 5)
15
See how flexible it is using *args
. Note it is not necessary to name *arg
s as args
. We can name it whatever we like. But it must be preceded with a *
.
2. **kwargs
**kwargs collects extra positional arguments as a dictionary.
Let’s return to our previous examples of function person
:
Task 2: Modify function person so that it accepts additional optional parameters phone_num, email and so on…as keywords. We modify our original function definition to accept a new argument **kwargs
which is a keyword argument as:
>>> def person(first_name, *args, **kwargs):
... print(first_name, end=" ")
... for names in reversed(args):
... print(names, end=" ")
... print()
... # Since kwargs is a dictionary
... # we can iterate using .items()
... for key, value in kwargs.items():
... print(key, value)
>>> person("Ram", "Chhetri", "Lal", phone_num="981128331", email="[email protected]")
Ram Lal Chhetri
phone_num 981128331
email anon@testmail.com
Since kwargs is of dictionary type. we can iterate over key, value using .items()
Notes:
*args
and**kwargs
are used to allow the function to accept a variable number of arguments*args
collects positional arguments as a tuple whereas**kwargs
as dictionaryargs
andkwargs
are just naming convention. You can name it whatever you like.*
and**
are also used in value unpacking