*args and **kwargs in Python

By Pradyumna Chippigiri

February 9, 2026


This is easy, just wanting to document this for quick reference incase i forget, cuz i keep forgetting this...


Firstly, args and kwargs are not keywords, they are just variables. (which has become a convention).. Everything is in the syntax * and **.

*args

*args shuould be used when we do not know how many positional arguments the caller will pass to the function.

def show_items(*args):
    for i, x in enumerate(args):
        print(i, x)
 
show_items("pen", "pencil", "eraser")
 

output :

0 pen
1 pencil
2 eraser

**kwargs

**kwargs should be used when we don’t know which named arguments the caller will pass to the function..

def show_settings(**kwargs):
    for k, v in kwargs.items():
        print(f"{k} = {v}")
 
show_settings(mode="fast", retry=3)

output :

mode = fast
retry = 3

Inside the function, kwargs is :

{"mode": "fast", "retry": 3}   # dict

Combining *args and **kwargs

When we want to pass both positional and named arguments to a function, we can use both *args and **kwargs.

def show_info(*args, **kwargs):
    for i, x in enumerate(args):
        print(i, x)
    for k, v in kwargs.items():
        print(f"{k} = {v}")
show_info("pen", "pencil", "eraser", mode="fast", retry=3)

output :

0 pen
1 pencil
2 eraser
mode = fast
retry = 3

* and ** when calling a function

we can also have * and ** even in the calling function as well, and not just in the called function.

def show_three(a, b, c):
    print(a, b, c)
 
items = ["pen", "pencil", "eraser"]
show_three(*items)   #  unpacks list into a,b,c
 

output :

pen pencil eraser

now lets see how we can pass ** in the calling function

def show_three(a, b, c):
    print(a, b, c)
 
data = {"a": "pen", "b": "pencil", "c": "eraser"}
show_three(**data)   # unpacks dict into a,b,c by key
 

output :

pen pencil eraser 

What happens when *args is in the middle of a function signature?

*args can appear in the middle, so when it appears like this, python usually has 2 pointers, one from the left and one more fron the right, and the left pointer increments and consumes the value, and the right pointer decrements and consumes the value, so the left out ones belong to the *mid variable as a tuple.

def demo(a, b, *mid, c, d):
    print("a =", a)
    print("b =", b)
    print("mid =", mid)
    print("c =", c)
    print("d =", d)
 
demo(1, 2, 3, 4, 5, 6, 7)

output :

a = 1
b = 2
mid = (3, 4, 5)
c = 6
d = 7