Use of *args and **kwargs
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
*args and **kwargs let a Python function accept a flexible number of arguments. They are useful when you are writing wrappers, forwarding calls, or designing APIs that need optional extra input without exploding the function signature.
What *args Actually Captures
*args collects extra positional arguments into a tuple.
Output:
The name args is conventional, but not magical. This works too:
What matters is the leading *, not the variable name.
What **kwargs Captures
**kwargs collects extra keyword arguments into a dictionary.
Output:
Again, the name kwargs is a convention. The ** is what tells Python to pack remaining named arguments into a mapping.
Packing and Unpacking Are Related Ideas
Inside a function definition, *args and **kwargs pack values together. At a call site, * and ** can unpack values back out.
Output:
This symmetry is why *args and **kwargs are so common in wrapper functions. You can accept flexible input and forward it with very little boilerplate.
A Useful Wrapper Example
Here is a simple timing decorator that forwards any positional and keyword arguments to the wrapped function:
Without *args and **kwargs, writing reusable wrappers like this would be much more awkward.
Parameter Order Still Matters
Python still enforces parameter ordering rules. A common pattern is:
Here:
- '
requiredis a normal positional-or-keyword parameter' - '
*argscollects extra positional values' - '
debugbecomes keyword-only because it appears after*args' - '
**kwargscollects any remaining named values'
Understanding that order makes function signatures much easier to read.
When They Are Helpful
Good uses include:
- decorators and wrappers
- pass-through helper functions
- plugin hooks that may accept optional metadata
- APIs that intentionally allow extra named options
Not every function needs them. If a function always expects exactly three clear parameters, explicit names are usually better than flexible catch-all parameters.
Common Pitfalls
The biggest mistake is using *args or **kwargs when the function really has a fixed, known contract. That makes code harder to read and hides what callers are supposed to provide.
Another common issue is forgetting that args is a tuple and kwargs is a dictionary. They are collected containers, not magic argument streams.
Developers also sometimes mix up packing and unpacking. def f(*args) packs extra positional values in a definition, while f(*values) unpacks an iterable at a call site.
Finally, forwarding **kwargs blindly can hide misspelled option names. If the receiving function does not expect a key, the error may show up far away from where the bad value entered the system.
Summary
- '
*argscollects extra positional arguments into a tuple.' - '
**kwargscollects extra keyword arguments into a dictionary.' - The same
*and**syntax can unpack values at call sites. - They are especially useful in wrappers, decorators, and pass-through helpers.
- Use them for flexibility, but prefer explicit parameters when the contract is fixed and known.

