Courses/Python Mastery/Module 7: Functions
Module 7 · Lesson 320 minBeginner

*args and **kwargs Demystified

Lesson goal
Accept any arguments — the pattern behind every flexible API.

*args and **kwargs Demystified

Sometimes a function should accept *any number* of inputs — print() does it, max() does it, and after this lesson, yours can too. The syntax looks cryptic; the idea is two sentences.

The two sentences

  • `*args` — "collect all extra positional arguments into a tuple"
  • `kwargs` — "collect all extra keyword arguments into a dict**"
  • That's genuinely the whole concept. Watch:

    code
    def demonstrate(*args, **kwargs):
        print("args:", args)
        print("kwargs:", kwargs)
    
    demonstrate(1, 2, 3, name="Aarav", age=16)

    Output:

    code
    args: (1, 2, 3)
    kwargs: {'name': 'Aarav', 'age': 16}

    The star gathers leftovers into a tuple; the double star gathers leftovers into a dict. Inside the function, they're ordinary containers — loop them, index them, len() them.

    A real example: add them all up

    code
    def add_all(*numbers):
        total = 0
        for n in numbers:
            total += n
        return total
    
    print(add_all(1, 2))            # 3
    print(add_all(1, 2, 3, 4, 5))   # 15
    print(add_all())                # 0 — empty tuple, no problem

    Compare with fixed parameters — add(a, b) handles exactly two, forever. add_all(*numbers) handles zero, two, or two hundred. Flexibility is the point.

    args and normal parameters can mix

    Normal parameters first, then *args collects the overflow:

    code
    def introduce(greeting, *names):
        for name in names:
            print(f"{greeting}, {name}!")
    
    introduce("Hello", "Aarav", "Diya", "Kabir")

    Output:

    code
    Hello, Aarav!
    Hello, Diya!
    Hello, Kabir!

    "Hello" went to the named parameter; everything after landed in names. The order rule: normal params → *args → kwargs**, always in that order.

    Where you've already used this (twice!)

    Every function you've defined with a flexible body:

    code
    def wrapper(*args, **kwargs):     # from the decorators world
        ...

    And the built-ins you've called all course:

    code
    print("a", "b", "c", sep="-")     # print accepts *values + **kwargs
    max(4, 9, 2)                      # max accepts any count

    Now you know *how* they work — the stars gather, the function loops.

    Unpacking: stars work in reverse too

    The stars also spread values out at call time:

    code
    def introduce(name, age):
        print(f"{name} is {age}")
    
    info = ("Diya", 15)
    introduce(*info)          # unpacks the tuple into two arguments!
    
    settings = {"name": "Kabir", "age": 16}
    introduce(**settings)     # unpacks the dict into keyword arguments

    *info turns a tuple into positional arguments; **settings turns a dict into keyword arguments. This pairing — gather with stars in the definition, spread with stars in the call — is how Streamlit and every flexible library passes settings around.

    Naming: the convention

    args and kwargs are just names — the stars are the magic:

    code
    def add_all(*values):        # totally fine
    def config(**options):       # also fine

    But *args, **kwargs is the universal convention — stick to it unless a better name truly helps.

    Common Errors & Fixes

  • `TypeError: introduce() takes 2 positional arguments but 3 were given` — the function lacks *args; add it if extra inputs are legal.
  • Order crash: `*args` before normal params — normal first, then *args, then **kwargs.
  • kwargs keys are stringskwargs["name"], never kwargs[name] (unless you have a variable holding "name").

  • ✅ Checkpoint

  • What do *args and **kwargs collect into? *(Tuple and dict)*
  • Correct parameter order? *(Normal → *args → **kwargs)*
  • What does introduce(*("Diya", 15)) do? *(Unpacks the tuple into two positional arguments)*
  • Name a built-in you've used that takes *args. *(print, max)*
  • Next: scope — where variables live, why they vanish, and the LEGB rule in five minutes.