Course Progress40%
🍎 Python Basics Topic 40 / 100
⏳ 8 min read

*args and **kwargs

Write functions that accept any number of arguments — the *args and **kwargs pattern used throughout real Python code.

"*args collects any number of positional arguments into a tuple. **kwargs collects any number of keyword arguments into a dictionary. Together they make your functions completely flexible."

— ShurAI

The Problem: Fixed Number of Parameters

Normal functions require exactly the number of arguments you declared. What if you don't know in advance how many there will be?

python — the limitation
def add(a, b):
    return a + b

add(1, 2)        # works
add(1, 2, 3)     # TypeError: add() takes 2 positional arguments but 3 were given

*args — Any Number of Positional Arguments

The * before a parameter name collects all extra positional arguments into a tuple. The name args is convention — the star is what matters:

python
def add(*args):
    print(type(args))   # <class 'tuple'>
    return sum(args)

print(add(1, 2))              # 3
print(add(1, 2, 3))          # 6
print(add(10, 20, 30, 40))   # 100
print(add())                  # 0 — empty tuple is fine
add(10, 20, 30) — all 3 packed into args tuple
add(
10
20
30
)
args = (10, 20, 30)
All positional arguments are bundled into a tuple called args.

Mixing Regular + *args

python
def greet(greeting, *names):
    """Say greeting to every name provided."""
    for name in names:
        print(f"{greeting}, {name}!")

greet("Hello", "Riya")
greet("Good morning", "Arjun", "Sneha", "Vikram")
output
Hello, Riya!
Good morning, Arjun!
Good morning, Sneha!
Good morning, Vikram!

**kwargs — Any Number of Keyword Arguments

The ** prefix collects all extra keyword arguments into a dictionary. Perfect when you want named, optional settings:

python
def show_profile(**kwargs):
    print(type(kwargs))   # <class 'dict'>
    for key, val in kwargs.items():
        print(f"  {key}: {val}")

show_profile(name="Riya", age=22, city="Mumbai")
print()
show_profile(product="Rice", price=280)
output
  name: Riya
  age: 22
  city: Mumbai

  product: Rice
  price: 280

Using Both Together

Order rule: regular first, then *args, then **kwargs:

python
def order_food(table, *dishes, **options):
    print(f"Table {table}:")
    print(f"  Dishes : {list(dishes)}")
    print(f"  Options: {options}")

order_food(
    5,
    "Biryani", "Naan", "Raita",
    spice="medium", takeaway=False
)
output
Table 5:
  Dishes : ['Biryani', 'Naan', 'Raita']
  Options: {'spice': 'medium', 'takeaway': False}

Quick Summary

*args
One star *
Collects positional args
Inside function: a tuple
Loop with: for x in args
**kwargs
Two stars **
Collects keyword args
Inside function: a dict
Loop with: for k,v in kwargs.items()

"*args and **kwargs are the secret behind Python's most flexible functions. Once you understand them, you'll see them used all the time in libraries."

— ShurAI

🧠 Quiz — Q1

Inside a function, what data type does *args give you?

🧠 Quiz — Q2

Inside a function, what data type does **kwargs give you?

🧠 Quiz — Q3

What is the correct order of parameters in a function definition?

🧠 Quiz — Q4

Given def f(**opts): print(opts), what does f(color="red", size=10) print?