Python Tutorial / Use Positional Arguments, Keywords and Defaults
Function arguments can be supplied by position or keyword, and defaults make selected inputs optional. Avoid mutable default objects when each call should start with fresh state.
Make argument meaning visible
Positional arguments bind in order; keyword arguments bind by parameter name. Supplying the same parameter twice is an error, as is placing an ordinary positional argument after a keyword argument. Keywords clarify calls with several options.
Parameters after a bare * are keyword-only. In the example, currency must be named explicitly so that the unit is visible at the call site.
For the relevant APIs and platform requirements, see Use Positional Arguments, Keywords and Defaults documentation.
Run keyword-only arguments and fresh-list defaults
Save the complete code below as arguments.py in a separate practice folder, using UTF-8. Run python arguments.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 format_expense(name, amount, *, currency="KRW"):
return f"{name}: {amount:,} {currency}"
def append_name(name, names=None):
if names is None:
names = []
names.append(name)
return names
print(format_expense("lunch", 8000))
print(format_expense(amount=9000, name="dinner", currency="KRW"))
print(append_name("A"))
print(append_name("B"))
Expected output:
lunch: 8,000 KRW dinner: 9,000 KRW ['A'] ['B']
Understand when a default is created
Default expressions are evaluated when the function definition executes, not afresh for every call. A definition such as def append_name(name, names=[]) reuses one list. Receiving None and creating a list inside the function avoids that shared default state.
Check if names is None when an explicitly supplied empty list should be retained. Using if not names would replace that valid empty list and change the caller’s intended sharing behavior.
Test the interface and mutation contract
Pass currency as a third positional argument and verify that the keyword-only rule is enforced. Separately create names = [] and call append_name("A", names): this intentionally mutates the caller’s list. Mutation of an explicitly passed object is a different issue from reuse of a default object.
A current-date or current-time expression used as a default can also freeze a value at definition time. When each call needs a fresh value, receive None and calculate it in the body. Choose a distinct sentinel if None itself must be an accepted meaningful argument.
The scope and mutable-object lesson helps separate rebinding a local name from changing the object shared with a caller.




