Introduction

People who are new to python programming finds hard to understand two types of function arguments python provides namely *agrs and **kwargs. Let me be clear about one thing, you need not necessarily name those arguments as by same name as above (args and kwargs) you can name those argument as your choice(eg- *agr , *agrs) what is important is that asterisk(*) symbol.

Note: for demonstration I will be using Jupyter Notebook

Let's take an example of *args

def fun(*args):
    print(args)
fun(1,2,3,4,5,'5.5', "rs")

Output:

(1, 2, 3, 4, 5, '5.5', 'rs')

Using *args we can give as many inputs as we want, but keeping on mind that arguments must be non-keyworded arguments function that uses *agrs(*any_name_by_user) returns all the values in tuple.

Another example of *args

def fun(*args):
    print(args)
fun(1,2,3,4,5,'5.5', name = "rajesh")

When I run this code I got error like this:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-3e9b260b8436> in <module>
      1 def fun(*args):
      2     print(args)
----> 3 fun(1,2,3,4,5,'5.5', name = "rajesh")

TypeError: fun() got an unexpected keyword argument 'name'

In above example, as we pass keyworded arguments it throws an TypeError 

Use case of *args

Let's say we have a function that adds up the numbers pass as arguments but the number of arguments are totally depend on user so,

How can we do that?

⇒The anwser is simply using *args in a function.

def add(*args):
    result = sum(args)
    print(result)
    
add(1,2,3,4,5)
add(1,2,3,4,5,6,7,8,9,10.5)

Output:

15
55.5

In above function at first we pass five arguments and in second time we pass ten arguments and function handles no matter how many numbers are passed as arguments.

Let's take a look on **kwargs

Using *agrs we are unable to give keyworded arguments what if we wanted to give keyworded arguments there where **kwargs comes into picture.

def fun(**kwargs):
    print(kwargs)
fun(name="shiv", age=22, faculty="computer")

Output:

{'name': 'shiv', 'age': 22, 'faculty': 'computer'}

Function with **kwargs returns values as dictionary.

# to access the values 
def fun(**kwargs):
    for key, values in kwargs.items():
        print(f"key: {key} ,  value:  {values}")
fun(name="shiv", age=22, faculty="computer")


Output:

key: name ,  value:  shiv
key: age ,  value:  22
key: faculty ,  value:  computer

Use case of **kwargs 

Let's say we want to store the information of a student(name,id,age,address,ph no) using only one function. So, is it possible to do that? The answer is yes using **kwargs.

def student_info(**kwargs):
    print(kwargs)

student_info(name="Shiv Shrestha",id = 10, age = 22, address="Nepal", ph_no = 9800000000 )  
{'name': 'Shiv Shrestha', 'id': 10, 'age': 22, 'address': 'Nepal', 'ph_no': 9800000000 }

Mostly the use of *args and **kwargs is in python decorator.

Conclusion

*args is used in a function that accepts non-keyworded arguments and **kwargs is used in a function whose task is to accepts the keyworded arguments. The first one return the accepted values in the form of tuple and latter one returns the accepted values in the form of dictionary.

Happy Learning:-)