1.2.29Introduction to Programming (Python)

` - args` and ` - kwargs` — flexible argument passing

1,840 words8 min readdifficulty · medium2 backlinks

WHY does this exist?

The * and ** are unpacking/packing operators. The names args and kwargs are just convention — what matters is the * and **.


WHAT exactly are they?

So * has two jobs depending on side:

Side *seq **dict
Definition (collect/pack) gather extra positionals → tuple gather extra keywords → dict
Call (spread/unpack) spread a list/tuple into positionals spread a dict into keyword args

HOW it works — derive from first principles

Start with the simplest thing and grow it.

Step 1 — a fixed function.

def add(a, b):
    return a + b
add(2, 3)   # 5

Why this step? Establishes the baseline rigidity: exactly 2 args allowed.

Step 2 — let Python pack extras into a tuple.

def add(*args):
    print(args)        # (2, 3, 4) — a TUPLE
    total = 0
    for x in args:
        total += x
    return total
add(2, 3, 4)   # 9

Why this step? The * tells Python: "any leftover positional values, stuff them into one tuple called args." Now the function works for any count.

Step 3 — keyword leftovers go into a dict.

def describe(**kwargs):
    print(kwargs)      # {'name': 'Ravi', 'age': 20} — a DICT
    for key, value in kwargs.items():
        print(f"{key} = {value}")
describe(name="Ravi", age=20)

Why this step? ** catches key=value pairs that have no matching named parameter, building a dictionary.

Step 4 — the canonical full ordering.

def f(a, b, *args, **kwargs):
    ...

The legal order in a definition is always: positional    *args    keyword-only    **kwargs\text{positional} \;\rightarrow\; \texttt{*args} \;\rightarrow\; \text{keyword-only} \;\rightarrow\; \texttt{**kwargs} Why? Python must first satisfy the named positionals, then sweep remaining positionals into *args, then sweep remaining keywords into **kwargs. **kwargs must be last because nothing can come after a "catch-all dict."

Figure — ` - args` and ` - kwargs` — flexible argument passing

Call-site unpacking (the mirror image)

def add(a, b, c):
    return a + b + c
 
nums = [1, 2, 3]
add(*nums)            # same as add(1, 2, 3) -> 6
 
opts = {'a': 1, 'b': 2, 'c': 3}
add(**opts)           # same as add(a=1, b=2, c=3) -> 6

Worked Examples


Forecast-then-Verify


Common Mistakes (Steel-manned)



Recall Feynman: explain to a 12-year-old

Imagine a teacher collecting homework. *args is one big tray: "throw any number of papers here, in order, and I'll keep them stacked." **kwargs is a labelled box: "if your paper has a name tag like name=Ravi, drop it in this box and I'll remember which tag goes with which paper." The teacher (the function) never knows ahead of time how many students show up — but the tray and the labelled box can hold any amount. And when the teacher hands the pile to another teacher, putting a * in front means "spread these papers back out one by one."


Flashcards

What does *args collect arguments into?
A tuple of all extra positional arguments.
What does **kwargs collect arguments into?
A dict of all extra keyword arguments.
Is args mutable?
No — it is a tuple (immutable).
What is the required parameter order in a definition?
positional, *args, keyword-only, **kwargs.
At a CALL site, what does f(*mylist) do?
Unpacks/spreads the list into separate positional arguments.
At a CALL site, what does f(**mydict) do?
Unpacks the dict into separate keyword arguments.
Why must **kwargs be last in a definition?
It is a catch-all dict; nothing can follow a parameter that absorbs all remaining keywords.
If you call f() where def f(*nums), what is nums?
An empty tuple ().
What does {**a, **b} do on conflicting keys?
Merges both dicts; keys in b (later) override those in a.
Are the names args/kwargs required by Python?
No — only the * and ** matter; the names are convention.
How do decorators forward arbitrary arguments?
By catching with *args, **kwargs and re-calling func(*args, **kwargs).

Connections

  • Functions and Parameters — the foundation *args/**kwargs extend.
  • Default Arguments — combine with catch-alls for flexible signatures.
  • Tuples — what *args produces.
  • Dictionaries — what **kwargs produces.
  • Decorators — heavy users of argument forwarding.
  • Unpacking Assignmenta, *rest = [1,2,3] uses the same star idea.

Concept Map

solved by

uses

packs positionals

packs keywords

collects into

collects into

at call site

spread list into

spread dict into

constrains

**kwargs must be

only * matters

Problem: unknown arg count

Flexible argument passing

Star operators * and **

*args

**kwargs

Tuple

Dict

Spread / unpack

Positional args

Keyword args

Definition order rule

Last position

Names are convention

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, kabhi-kabhi aapko pata hi nahi hota ki function ko kitne arguments milenge — 2 milenge ya 10. Aise me fixed parameters likhna bahut rigid ho jata hai. Yahin par *args aur **kwargs kaam aate hain. *args ek bada dabba hai jo saare extra positional values ko ek tuple me pack kar leta hai. **kwargs doosra dabba hai jo saare keyword arguments (jaise name="Ravi") ko ek dictionary me pack kar leta hai. Naam args/kwargs zaroori nahi hai — asli magic to * aur ** symbol ka hai.

Sabse important baat: * ka kaam side ke hisaab se badalta hai. Function ki definition me * collect karta hai (values ko tuple/dict me daalta hai). Lekin function ko call karte waqt * ulta kaam karta hai — woh ek list ya dict ko spread/khol deta hai. Jaise add(*nums) matlab nums list ko alag-alag arguments me tod do. Isi symmetry ki wajah se aap arguments ko ek function se doosre function me aaram se forward kar sakte ho.

Order yaad rakhna zaroori hai: pehle normal positional, phir *args, phir keyword-only, aur sabse last me **kwargs. Agar aap **kwargs ko beech me ya pehle daaloge to SyntaxError aayega, kyunki woh "sab kuch catch karne wala dict" hai — uske baad kuch nahi aa sakta. Decorators, logging functions, flexible APIs — yeh sab isi concept par tike hote hain, isliye yeh interview aur real coding dono me bahut kaam aata hai.

Go deeper — visual, from zero

Test yourself — Introduction to Programming (Python)

Connections