Python *args and **kwargs explained
*args syntax, **kwargs syntax, combining argument types, argument order rules, unpacking into function calls, practical use cases
Variable Arguments
*args collects extra positional arguments into a tuple. **kwargs collects extra keyword arguments into a dictionary. Both names are conventional — only the * and ** matter.
def add(*numbers):
return sum(numbers)
print(add(1, 2, 3)) # 6
print(add(10, 20)) # 30
def describe(**info):
for k, v in info.items():
print(f"{k}: {v}")
describe(name="Alice", age=30, city="NY")
Combining All Types
Argument order rule: positional → *args → keyword-only → **kwargs. Breaking this order raises a SyntaxError.
def mixed(a, b, *args, sep=" ", **kwargs):
print(a, b, args, sep, kwargs)
mixed(1, 2, 3, 4, sep=",", x=10)
# 1 2 (3, 4) , {'x': 10}
Unpacking on the Call Side
nums = [1, 2, 3]
print(add(*nums)) # unpack list as positional args
params = {"name": "Alice", "age": 30}
describe(**params) # unpack dict as keyword args
The *args and **kwargs pattern is used extensively in Python libraries for building flexible APIs, wrappers, and decorators that need to forward arguments transparently. When writing a decorator, always accept *args, **kwargs in the wrapper so it can wrap any function regardless of signature. Positional-only parameters (before a / in the signature) and keyword-only parameters (after a bare *) are advanced signature constraints introduced in Python 3 that library authors use to control how their APIs are called.
