Python Tutorial / Collect and Unpack Arguments with *args and **kwargs
In a function definition, *args collects extra positional arguments into a tuple and **kwargs collects extra keyword arguments into a dictionary. At a call site, * and ** unpack existing collections in the opposite direction.
Distinguish collection from expansion
args and kwargs are conventional names; the star syntax determines their role. Do not make every function variadic when its inputs are fixed and clear: broad interfaces can make accepted fields and mistakes harder to see.
| Location | Expression | Effect |
|---|---|---|
| Definition | def f(*args) | Collect extra positional arguments |
| Definition | def f(**kwargs) | Collect extra keyword arguments |
| Call | f(*values) | Expand iterable items into positional arguments |
| Call | f(**options) | Expand string-keyed mapping entries into keywords |
For the relevant APIs and platform requirements, see Collect and Unpack Arguments with *args and **kwargs documentation.
Run a variable-length total and option description
Save the complete code below as varargs.py in a separate practice folder, using UTF-8. Run python varargs.py in a terminal with your project virtual environment selected. Outside a virtual environment on macOS or Ubuntu, use python3 when that is your interpreter command.
def total(*amounts, fee=0):
return sum(amounts) + fee
def describe(**fields):
return ", ".join(f"{key}={value}" for key, value in sorted(fields.items()))
values = [3500, 8000, 2500]
print(total(*values, fee=500))
options = {"category": "food", "currency": "KRW"}
print(describe(**options))
Expected output:
14500 category=food, currency=KRW
Reject duplicate keywords and unintended expansion
Keys expanded with ** must be strings and must match parameters accepted by the target. A call such as f(amount=1, **{"amount": 2}) raises TypeError because one argument is supplied twice. Dictionary merging and duplicate call arguments follow different rules.
Expanding a string with * supplies one character at a time. total(*"123") does not pass the integer 123. When a collection has one clear meaning, a single explicit list parameter may communicate that meaning better than arbitrary positional arguments.
Keep the accepted interface controlled
Accepting **kwargs does not justify forwarding unchecked input into external APIs or SQL. Validate required fields and allowed option names before forwarding them. Quietly accepting misspelled options makes failures harder to diagnose.
- Append zero to values and verify the same total.
- Omit fee and verify that its default zero applies.
- Try supplying a keyword both explicitly and through an expanded mapping, then explain the error.
Use variadic arguments when they model the problem, and keep ordinary named parameters for options whose meaning should remain visible.




