Most Python developers know how to call a function.
def copy(item, is_move):
print("Copy", item)
if is_move:
print("Delete", item)
copy("item1", True)
copy("item2", False)
At first glance, nothing seems unusual but look closely at the function calls.
copy("item1", True)
copy("item2", False)
What does True mean? What does False mean?
Unless you remember the parameter list, you're guessing.
This is a classic example of control coupling. A boolean flag controls the behavior of the function, but the meaning of the flag is hidden inside a positional argument.
The code works, but the call site forces readers to mentally jump back to the function definition.
Now look at the same calls written differently:
copy("item1", is_move=True)
copy("item2", is_move=False)
Suddenly the intent becomes obvious.
This is one of the reasons Python programmers often prefer keyword arguments for flags and optional settings. The code becomes self-documenting.
Many developers assume that because the function is defined like this:
def copy(item, is_move):
the arguments must be passed positionally. After all, that's what we've been doing:
copy("item1", True)
So why is this legal?
copy("item1", is_move=True)
The answer reveals something many Python developers never fully realize:
Parameters in Python are positional-or-keyword by default.
That means Python lets you provide them either by position:
copy("item1", True)
or by name:
copy("item1", is_move=True)
The parameter name isn't just documentation. It's actually part of the function's calling interface.
But here's where things get interesting.
If parameters can be supplied by name, then what actually determines where the values go?
The answer is The parameter names and if names determine where values go, then the order becomes irrelevant. Which means this works:
copy(is_move=True, item="item1")
copy(is_move=False, item="item2")
Read that again...the arguments are reversed and Python matches them by parameter name. Effectively, Python sees:
item = "item1"
is_move = True
and
item = "item2"
is_move = False
regardless of the order in which they were written.
Once you see it, many Python APIs suddenly make more sense:
sorted(items, reverse=True)
open("data.txt", encoding="utf-8")
print("Hello", end="")
The parameter names aren't just there for documentation. They're part of the language's argument matching system.
It's one of those details that separates writing Python from understanding Python.
Written by Loek van den Ouweland on June 4, 2026.