What do double star/asterisk and star/asterisk mean in a function call?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python function calls, * and ** are unpacking operators. * expands an iterable into positional arguments, while ** expands a mapping into keyword arguments. The same symbols also appear in function definitions, where they collect arguments instead of expanding them, so it helps to learn both directions together.
* in a Function Call
* takes a sequence such as a list or tuple and unpacks its elements into separate positional arguments.
Without *, the function would receive one list argument instead of three positional arguments.
You can also mix explicit positional arguments with unpacked values.
That call is equivalent to show(1, 2, 3, 4).
** in a Function Call
** takes a mapping, usually a dictionary, and unpacks its keys and values into keyword arguments.
This works only if the dictionary keys match the parameter names. If the mapping has an unexpected key, Python raises TypeError.
*args and **kwargs in Definitions
In a function definition, the meaning flips:
- '
*argscollects extra positional arguments into a tuple' - '
**kwargscollects extra keyword arguments into a dictionary'
At the call site, * and ** expand values outward. In the function definition, they gather values inward.
Why This Is Useful for Wrappers
These forms appear constantly in decorators, wrappers, and helper functions that forward calls without knowing the target signature in advance.
This works because the wrapper collects arbitrary inputs and then forwards them with unpacking.
Argument Order Still Matters
Even with unpacking, normal Python binding rules still apply. Positional arguments come before keyword arguments, and you cannot provide the same argument twice.
Here precision is keyword-only because it appears after *values in the definition.
Multiple Unpackings Can Be Combined
Python also allows more than one unpacking source in the same call, as long as the final argument binding is valid.
This flexibility is useful when arguments come from several sources and you want to combine them cleanly at the call site.
Common Pitfalls
A common mistake is assuming * and ** always mean multiplication and exponentiation. In function calls and definitions, they often mean unpacking and collecting instead.
Another is passing a dictionary with keys that do not match the function's parameter names. ** does not rename keys.
Developers also mix up the call-site meaning and the definition-side meaning. In a call, * expands. In a definition, *args collects.
Summary
- In a function call,
*unpacks an iterable into positional arguments. - In a function call,
**unpacks a mapping into keyword arguments. - In a function definition,
*argscollects extra positional arguments. - In a function definition,
**kwargscollects extra keyword arguments. - Unpacking is especially useful in wrappers, decorators, and dynamic API calls.

