*args and **kwargs in Python, Explained
*args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dict. Here's how they work, how to use them, and why they're essential for flexible functions and decorators.
In Python, *args lets a function accept any number of extra positional arguments (collected into a tuple), and **kwargs lets it accept any number of extra keyword arguments (collected into a dictionary). They make functions flexible — accepting however many arguments a caller provides — and they’re essential for writing wrappers and decorators.
The single * and double ** are what matter; args and kwargs are just the conventional names.
*args — variable positional arguments
*args gathers any extra positional arguments into a tuple:
def total(*args):
return sum(args) # args is a tuple, e.g. (1, 2, 3)
total(1, 2, 3) # 6
total(1, 2, 3, 4, 5) # 15 — any number works
Inside the function, args is an ordinary tuple you can loop over or index. Use it when callers pass a variable number of plain values.
**kwargs — variable keyword arguments
**kwargs gathers any extra named arguments into a dictionary:
def describe(**kwargs):
for key, value in kwargs.items():
print(f"{key} = {value}")
describe(name="Ana", age=30)
# name = Ana
# age = 30
Inside the function, kwargs is a normal dict. Use it for flexible named options.
Using them together
You can combine both, but the order is fixed: regular parameters, then *args, then keyword-only parameters, then **kwargs:
def func(a, b, *args, **kwargs):
print(a, b) # required positionals
print(args) # extra positionals as a tuple
print(kwargs) # extra keywords as a dict
func(1, 2, 3, 4, x=5, y=6)
# 1 2
# (3, 4)
# {'x': 5, 'y': 6}
* = positional, collected into a tuple. Two stars ** = keyword, collected into a dict. The order in a signature is always: regular params → *args → keyword-only → **kwargs.
Unpacking: the other direction
The same * and ** also unpack a collection into arguments when calling a function:
nums = [1, 2, 3]
total(*nums) # same as total(1, 2, 3)
opts = {"name": "Ana", "age": 30}
describe(**opts) # same as describe(name="Ana", age=30)
So */** collect arguments in a definition and spread them in a call — symmetric and very handy.
Why decorators need them
This is the killer use case. A decorator wraps any function, so its wrapper must accept and forward whatever arguments come in:
def logged(func):
def wrapper(*args, **kwargs): # accept anything
print(f"calling {func.__name__}")
return func(*args, **kwargs) # forward it all
return wrapper
Without *args, **kwargs, a decorator would only work on functions with a fixed signature. This pattern is why they’re so common.
Common mistakes
- Wrong order in the signature —
**kwargsmust be last,*argsbefore it. - Forgetting to forward both in a wrapper — drop
**kwargsand keyword arguments silently disappear. - Confusing collect vs unpack —
*in a definition gathers;*in a call spreads. - Overusing them — when a function has known parameters, name them explicitly;
*args, **kwargseverywhere hides the real interface.
Where this fits
*args and **kwargs are a Phase 3 function skill in the Python roadmap, and they’re prerequisite knowledge for decorators and flexible class constructors.
They’re explained with examples in Python in One Month and used throughout the job-ready Python in Three Months.
One star for positional, two for keyword — collect in the definition, spread in the call. That’s the whole feature.
Frequently asked questions
What do *args and **kwargs mean in Python?
*args lets a function accept any number of extra positional arguments, collected into a tuple. **kwargs lets it accept any number of extra keyword arguments, collected into a dictionary. The names args and kwargs are convention — what matters is the single star (positional) and double star (keyword).
What is the difference between *args and **kwargs?
*args gathers extra positional arguments into a tuple, so you access them by position. **kwargs gathers extra keyword (named) arguments into a dictionary, so you access them by name. Use *args when callers pass a variable number of plain values, and **kwargs when they pass named options.
Do I have to use the names args and kwargs?
No. Only the * and ** matter to Python; the names are convention. You could write *values and **options and it would work identically. But args and kwargs are the universally understood names, so using them makes your code instantly readable to other Python developers.
What is the correct order of parameters with *args and **kwargs?
Regular positional parameters come first, then *args, then keyword-only parameters with defaults, then **kwargs last. The order is: def func(a, b, *args, key=value, **kwargs). *args must come before **kwargs, and **kwargs is always last.