*args, **kwargs & Argument Unpacking
Intermediate*args collects extra positional arguments into a tuple, **kwargs collects extra keyword arguments into a dict — and the same stars unpack sequences/dicts INTO calls.
Overview
The star syntax works in two directions. In a function SIGNATURE, *args gathers any number of positional arguments and **kwargs gathers any number of keyword arguments — this is how print(), dict(), and every decorator you'll ever write accept anything. In a CALL, * unpacks a sequence into separate arguments and ** unpacks a dict into keyword arguments. Add keyword-only parameters (after *) and you have Python's full argument toolkit — used heavily in FastAPI, pytest and every serious library.
Collecting: *args and **kwargs
Order in a signature: positional, *args, keyword-only, **kwargs. Names args/kwargs are convention — the stars do the work.
def order_summary(customer, *items, express=False, **meta):
print(customer, "ordered", len(items), "items")
print("items:", items) # tuple
print("express:", express)
print("meta:", meta) # dict
order_summary("Asha", "pen", "book", express=True, coupon="NEW10", city="Pune")
# Asha ordered 2 items
# items: ('pen', 'book')
# express: True
# meta: {'coupon': 'NEW10', 'city': 'Pune'}
# The universal pass-through signature (decorators use this)
def log_call(func):
def wrapper(*args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs) # forward everything untouched
return wrapperUnpacking Into Calls & Assignments
The same stars explode containers at call sites. Star-unpacking also works in assignments (first, *rest) and in building lists/dicts (merging).
def volume(l, w, h):
return l * w * h
dims = [3, 4, 5]
print(volume(*dims)) # volume(3, 4, 5) -> 60
config = {"l": 2, "w": 3, "h": 4}
print(volume(**config)) # keyword-unpack -> 24
# Assignment unpacking
first, *rest = [1, 2, 3, 4]
print(first, rest) # 1 [2, 3, 4]
*init, last = [1, 2, 3, 4]
print(init, last) # [1, 2, 3] 4
# Merging
a, b = {"x": 1}, {"y": 2}
merged = {**a, **b, "z": 3} # {'x': 1, 'y': 2, 'z': 3}
combined = [*range(3), *"ab"] # [0, 1, 2, 'a', 'b']Key Points to Remember
- 1Signature: def f(pos, *args, kw_only=None, **kwargs) — that exact order
- 2*args is a tuple; **kwargs is a dict
- 3f(*seq) and f(**mapping) unpack INTO a call — the mirror image
- 4wrapper(*args, **kwargs) is the universal forwarding pattern behind every decorator
Interview Questions
Sign in to ask AriaExplain *args and **kwargs. Why do decorators use def wrapper(*args, **kwargs)?
What does {**dict1, **dict2} do, and which value wins on duplicate keys?
How do you force callers to pass an argument by keyword only?
Ask Aria about *args, **kwargs & Argument Unpacking
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.