Parameter Unpacking: *args and **kwargs#
Python functions can accept flexible argument lists using *args (extra positional → tuple) and **kwargs (extra keyword → dict). Unpacking also works at call time with * and **.
How to use this page
Builds on Functions and Scope. Used heavily in decorators and wrappers.
At a glance
| Track | Python Advanced → Advanced Functions |
| Sections | 7 major topics |
| Outline | Use the right-hand TOC to jump |
Topics: *args — variadic positional · **kwargs — variadic keyword · Keyword-only parameters (PEP 3102) · Positional-only parameters (PEP 570, 3.8+) · Unpacking at call site · Decorator wrapper pattern · Exhausting iterables into arguments
*args— variadic positional**kwargs— variadic keyword- Keyword-only parameters (PEP 3102)
- Positional-only parameters (PEP 570, 3.8+)
- Unpacking at call site
- Decorator wrapper pattern
- Exhausting iterables into arguments
*args — variadic positional#
*args is a convention — name it anything, but * is required.
Ordering rules in definition#
def f(a, b, *args, c=0):
...
# a, b — required positional
# *args — captures rest
# c — keyword with default
**kwargs — variadic keyword#
def configure(**kwargs):
for k, v in kwargs.items():
print(f"{k}={v}")
configure(host="localhost", port=8080)
Must come after *args (or after bare * for keyword-only section):
Keyword-only parameters (PEP 3102)#
def connect(host, port, *, timeout=30, ssl=True):
...
connect("localhost", 8080, timeout=60)
# connect("localhost", 8080, 60) # TypeError
Bare * forces following params to be keyword-only.
Positional-only parameters (PEP 570, 3.8+)#
/ separates positional-only from positional-or-keyword.
Unpacking at call site#
def f(a, b, c):
return a + b + c
args = (1, 2, 3)
f(*args) # 6
kwargs = {"a": 1, "b": 2, "c": 3}
f(**kwargs)
f(1, *[2, 3])
f(**{"a": 1}, **{"b": 2, "c": 3})
Merge dicts into kwargs#
defaults = {"timeout": 30, "retries": 3}
overrides = {"timeout": 60}
call(**{**defaults, **overrides}) # timeout=60
Decorator wrapper pattern#
from functools import wraps
def decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
# forward everything to wrapped function
return fn(*args, **kwargs)
return wrapper
Universal forwarding — why decorators use *args, **kwargs.
Exhausting iterables into arguments#
Requires exact count unless using *args.
Interview traps (quick reference)#
| Trap | What goes wrong | Safe approach |
|---|---|---|
**kwargs before *args |
SyntaxError | *args then **kwargs |
| Wrong unpack count | TypeError | Match signature |
| Mutating kwargs dict | Affects caller | Copy if needed |
| Keyword-only forgotten | TypeError on call | Document API |
Mental model checklist#
- What type is
argsinsidedef f(*args)? - What does
f(**d)require about keys? - What does bare
*in a signature mean? - Why do decorators use
*args, **kwargs?
What's next#
| Topic | Page |
|---|---|
| Decorators | Decorators |
| Functions and scope | Functions and Scope |
| Callable objects | Callable Objects |