What is the difference between positional and keyword arguments in Python?
Positional arguments are matched by their position in the call; keyword arguments are matched by name and can appear in any order. Python 3 also introduced positional-only (/) and keyword-only (*) separators to enforce calling conventions in function signatures.
How to think about it
The question sounds basic but it branches into some genuinely useful territory: the / and * separators that library authors use to make APIs future-proof, and the mutable default argument trap that trips up even experienced engineers.
The core idea: Python matches arguments to parameters in one of two ways — by position (the order you wrote them) or by name (using param=value syntax). You can mix both in a single call, but positionals must come before keyword arguments.
See all the forms in one go
Why the separators matter
The / separator says “parameters before me cannot be passed by name”. This lets library authors rename a positional parameter later without breaking callers. You see it in Python builtins — len(obj=[1,2,3]) raises a TypeError because len declares its argument positional-only.
The * separator says “parameters after me must be passed by name”. It forces callers to be explicit, which is valuable when a function takes several flags that are easy to get in the wrong order.
The default value sharp edge
Default values are evaluated once at function definition, not on each call — a sharp edge when the default is mutable:
# Bug: all calls share the same list
def append_to(val, lst=[]):
lst.append(val)
return lst
# Fix
def append_to(val, lst=None):
if lst is None:
lst = []
lst.append(val)
return lst