What are *args and **kwargs and How to use them

Deepanshu Bhalla 2 Comments
This article explains the concepts of *args and **kwargs and how and when we use them in python program. Seasoned python developers embrace the flexibility it provides when creating functions. If you are beginner in python, you might not have heard it before. After completion of this tutorial, you will have confidence to use them in your live project.
Table of Contents

Introduction : *args

args is a short form of arguments. With the use of *args python takes any number of arguments in user-defined function and converts user inputs to a tuple named args. In other words, *args means zero or more arguments which are stored in a tuple named args.

When you define function without *args, it has a fixed number of inputs which means it cannot accept more (or less) arguments than you defined in the function.

In the example code below, we are creating a very basic function which adds two numbers. At the same time, we created a function which can sum more than 2 numbers. Even the function can take less than 2 arguments (zero argument will also work!)

Sum : Only 2 arguments
def add(x,y):
     print(x + y)

add(5,5) #Works and returns 10

add(5,5,6)
TypeError: add() takes 2 positional arguments but 3 were given
Sum : Any number of arguments
def add(*args):
     print(sum(args))
    
add(5,5,6)
Output : 16
args kwargs python

How to get each argument?

You can extract arguments based on index like we get a value from tuple based on index position args[0] refers to first argument as indexing in python starts from zero.
def add(*args):
     print(args[0])
     print(args[1])
     print(args[2])
    
add(5,5,6)
Output :
5
5
6
It is not mandatory to use only keyword named args. You can use any naming convention other than args. Refer the code below wherein I used x instead of args-
def add(*x):
   return sum(x)
add(5,5,6)
How to use args in loop?
You can access arguments in loop by running it over args tuple.

In this example, we are creating a flag showing categorization of High/Medium/Low based on user inputs. If a value divided by 100 is greater than 7 should be indicated as "High". If it is greater than 5 and less than or equal to 7, it should be shown as "Medium". Otherwise it should be categorized as "Low".

def myfun(*args):
    for arg in args:
        if arg/100 > 7:
            print('High')
        elif arg/100 >5:
            print('Medium')
        elif arg/100 >0:
            print('Low')

myfun(100, 600, 900)

Output :
Low
Medium
High
If you want to store the result in a list, you can do this by creating an empty list initially and then start appending in an iterative matter in loop. The following code produces a list named l.
l = []
def myfun(*args):
    for arg in args:
        if arg/100 > 7:
            flag = 'High'
        elif arg/100 >5:
            flag = 'Medium'
        elif arg/100 >0:
            flag = 'Low'
        l.append(flag)
    return l

myfun(800,600,100)

How to pass lists / tuples in function?

By using * operator, you can unpack a list or tuple. In simple words, it refers to removing brackets (square brackets of list or round brackets of tuple). Think of *[1, 2, 3] as 1, 2, 3
k = [100, 600, 900]
myfun(*k)

Output :
Low
Medium
High

How to include both fixed and dynamic no. of arguments?

Python lets you to include both fixed argument and dynamic number of arguments using *args. It is important to note that it is required to include fixed argument. However you can ignore passing dynamic arguments and it won't return error.

Here we are creating a simple function which adds all the salary components. It comprises of base, variable and other allowances. It is mandatory to include Base salary. Other components you can ignore or include as per need.

def salary(base, *args):
    return base + sum(args)

salary(1000, 3000, 4000) # 8000
salary(1000) # 1000
salary() # Don't work, need to include base argument
How to check if arguments are passed in a function
By using not operator, you can find out that the arguments were not passed. len(args) is used to calculate the number of passed arguments. str( ) is used to convert the result into string format so that it can be concatenated with the text.
def test(*args):
    if not args:
        print("Note : You have not passed any argument")
    else:
        print("You have passed " + str(len(args)) + " arguments")

test(1,5,8)
You have passed 3 arguments

test()
Note : You have not passed any argument

How to use *args in lambda function?

The beauty of lambda function is that you can write your user defined function in a single line of code.
add = lambda *args: sum(args)
add(1,2,3,4)

#To pass a list to function
mylist = [1, 2, 3, 4]
add(*mylist)
Let's take another example : Suppose you want to multiply all the values specified in arguments. reduce( ) function allows us to apply function (multiplication) on first two values and then iterate again on the result with the third value and keeps going on till the last argument.
from functools import reduce
def my_func(*args):
    return reduce((lambda x, y: x * y), args)

my_func(1, 2, 3, 4)

How to use *args in list comprehension?

List comprehension makes coding more readable and is generally faster than For loop and lambda function.

In this example, we are selecting all the even numbers which are divisible by 2.

def even(*args):
    print([n for n in args if n%2 == 0])

even(1,2,3,4)

Output : [2, 4]

What is **kwargs?

**kwargs stands for keyword arguments. It is very similar to *args in terms of its objective but there are some differences explained below -
  1. **kwargs creates dictionary whereas *args creates tuple.
  2. By using **kwargs you can name your arguments which is not possible in *args.
def test2(**kwargs):
    print(kwargs)
    print(kwargs.keys())
    print(kwargs.values())

test2(a=1, b=3)

Output :
{'a': 1, 'b': 3}
dict_keys(['a', 'b'])
dict_values([1, 3])
Strings of each keyword are the keys of the dictionary and values assigned after = symbol are the values of the dictionary. It is also called named arguments.

How to use both args and kwargs

def myfun(*args, **kwargs):
    return sum(args) + sum(kwargs.values())

myfun(1,2, a=1, b=3)
Output : 7

myfun()
Output : 0

Examples : Uses of kwargs

Suppose you need to build a conditional statement which says sum of all the arguments if a fixed named argument called flag is set 'Yes'. Otherwise ignore the calculation and don't sum values and also throws a message which hints users why calculation has been ignored.
def calc(flag='Yes', **i):
    if flag == 'Yes' :
        return sum(i.values())
    else :
        print("Flag is set No")

calc(x=17, y=20)
Output : 37

calc(flag='No', x=17, y=20)
Output : Flag is set No
If you observe default value of named argument called flag is Yes so we don't need to specify it when we used this code calc(x=17, y=20).
Like args, any keyword other than kwargs can be used preceded by **. In the above example, we used i instead of kwargs.

Suppose you are asked to create a dynamic user-defined function which calculates total salary depending upon user inputs of performance rating and salary increment (hike).

In the following program, we check the keyword arguments by using in operator. For example, 'rating' in kwargs

def salary(base=0, **kwargs):
    if 'rating' in kwargs and kwargs['rating'] == 'high':
        if 'hike' in kwargs:
            hike = kwargs['hike']
        else:
            hike = 0.1
        return round(base*(1+hike), 2)
    else:
        if 'hike' in kwargs:
            hike = kwargs['hike']
        else:
            hike = 0.05
        return round(base*(1+hike), 2)
#If rating is not specified, it will be assumed "average" performer with 5% hike
salary(base=10000)
    
#Default hike for average performers 5%
salary(base=10000, rating='average')

#Default hike for high performers 10%
salary(base=10000, rating='high')

#Custom hike for average performers 7%
salary(base=10000, rating='average', hike =0.07)

#Custom hike for high performers 12%
salary(base=10000, rating='high', hike =0.12)

How to use arguments in Pandas Dataframe

In this example, we would show you multiple ways to include keyword arguments in dataframe. The most straightforward way to include arguments is to pass them in apply( ) function as named in user-defined function. Another way is to use args= parameter.
import pandas as pd
df = pd.DataFrame({'x1':[11,30,17]})

def myfun(row, l_limit=0, u_limit=0):
    if l_limit <= row['x1'] <= u_limit:
        return 1
    elif row['x1'] > u_limit:
        return 2

df.apply(myfun, axis=1, l_limit=10, u_limit=20)
df.apply(myfun, axis=1, args=(10,20))

Bad practices in using args

It is always good to practice what we have learnt but we sometimes use it in incorrect way just for the sake of learning new concepts. Then we got a habit of using it in real-world data situations. See the example below wherein instead of using lambda and reduce functions we are considering arguments based on index. It works only when the number of arguments are exactly the same defined in function. For example, args[0]+args[1]+args[2] works only when 3 arguments are passed.
Smart Way
def add(*args):
    return reduce(lambda x,y:x+y, args)

add(3,4,5)
Stupid Way
def add2(*args):
    return args[0]+args[1]+args[2]

add2(3,4,5) #Works

add2(3,4) #Error

Related Posts
Spread the Word!
Share
About Author:
Deepanshu Bhalla

Deepanshu founded ListenData with a simple objective - Make analytics easy to understand and follow. He has over 10 years of experience in data science. During his tenure, he worked with global clients in various domains like Banking, Insurance, Private Equity, Telecom and HR.

2 Responses to "What are *args and **kwargs and How to use them"
  1. Hi, Easy to understand since u provide detailed step by step explanation. Thank you!

    ReplyDelete
  2. Well explained, on point, well covered..! Thankyou Sir..!

    ReplyDelete
Next → ← Prev