Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteIn a Python function definition, *args collects extra positional arguments into a tuple, while **kwargs collects extra keyword arguments into a dictionary. In a function call, the same markers do the reverse: *iterable unpacks values as positional arguments, and **mapping unpacks entries as keyword arguments. Knowing whether the markers collect or unpack depends on whether they appear in a definition or a call.
What *args and **kwargs collect
The names args and kwargs are conventions, not special Python identifiers. The asterisks determine the behavior. This function shows both kinds of collection:
def describe(first, *args, **kwargs):
print("first:", first)
print("extra positional:", args)
print("extra keywords:", kwargs)
describe("hello", 1, 2, color="blue")
first receives "hello". The extra positional values, 1 and 2, are collected in args, a tuple: (1, 2). The extra keyword argument is collected in kwargs, a dictionary: {"color": "blue"}. Keywords that match explicitly declared parameters bind to those parameters instead of being collected.
The Python 3.14.8 Tutorial describes the positional behavior this way: “These arguments will be wrapped up in a tuple (see Tuples and Sequences).” Python Tutorial: Arbitrary Argument Lists
#1 Best Overall
Collection in a definition versus unpacking in a call
In a definition, the markers gather arguments supplied by the caller. At a call site, they unpack an iterable or mapping into arguments. These are related but distinct operations.
| Syntax | Where it appears | What it does | Result or input |
|---|---|---|---|
def f(*args): |
Function definition | Collects remaining positional arguments | A tuple inside the function |
def f(**kwargs): |
Function definition | Collects remaining keyword arguments | A dictionary inside the function |
f(*items) |
Function call | Unpacks an iterable into positional arguments | Values supplied to the call |
f(**options) |
Function call | Unpacks a mapping into keyword arguments | Named values supplied to the call |
For example, these values can supply the two parameters of greet:
Rank #2
def greet(name, punctuation="!"):
return f"Hello, {name}{punctuation}"
positional = ["Ada"]
options = {"punctuation": "."}
greet(*positional, **options)
The call is equivalent to greet("Ada", punctuation="."). The iterable supplies positional values; the mapping supplies keyword values. Keys unpacked with ** must be strings usable as keyword names, and the resulting call must not assign the same parameter twice.
How keyword-only parameters work
Any parameters declared after *args must be passed by keyword. This lets a function accept a variable number of positional values while keeping options clearly named:
Recommended Free Tools
def log(message, *args, sep=" "):
return message + sep + sep.join(map(str, args))
log("values:", 1, 2, sep=" | ")
Here, message binds first, 1 and 2 go into args, and sep is keyword-only. A bare * can create the same boundary without collecting extra positional arguments:
def connect(host, *, timeout):
...
connect("example.com", timeout=5)
Python also supports a slash (/) in a signature to mark preceding parameters as positional-only. The slash and the star are separate controls: / limits how earlier parameters may be supplied, while * marks where keyword-only parameters begin.
Forward arguments through a wrapper
A wrapper can accept arguments it does not interpret and forward them to another function:
def wrapper(x, *args, **kwargs):
return target(x, *args, **kwargs)
The wrapper consumes x and passes it along with the remaining positional and keyword arguments. It can also inspect or change kwargs before forwarding, but the wrapper should make clear which options it handles and which it passes on. For a stable public interface, explicitly naming supported parameters is often easier to understand and validate than accepting every possible argument.
Best Value
Common binding errors and how to diagnose them
- Giving a parameter two values:
f(1, x=2)raisesTypeErrorif the first positional argument already binds tox. Supply it once, either positionally or by keyword. - Using an unknown keyword: a call such as
f(color="blue")fails if the function has nocolorparameter and no**kwargscollector. - Passing a keyword-only parameter positionally: if it follows
*argsor a bare*, use its name in the call. - Expecting a list or tuple at the call site:
*argsin a definition creates a tuple, while**kwargscreates a dictionary. The variables themselves are ordinary local names. - Confusing collection with unpacking:
def f(*args)gathers values;f(*items)expands an iterable. Check whether the syntax is in a definition or a call.
Choose a signature that communicates the function’s interface
Use explicit parameters when the supported inputs are known and should be discoverable from the signature. Add *args when a function genuinely accepts an arbitrary number of positional values, and **kwargs when it needs to accept arbitrary named options or transparently forward them. Variadic arguments offer flexibility, but can make unsupported or misspelled options harder to catch at the function boundary.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




