Python Positional-Only Parameters: Syntax and Use Cases
Learn how Python's positional-only parameters work, why they matter for API design, and how to use them correctly in your functions.
In Python, positional-only parameters let you define function arguments that cannot be passed by keyword. The syntax uses a / in the parameter list. This feature, introduced in Python 3.8, gives you explicit control over how callers interact with your function's signature.
What Are Positional-Only Parameters?
A parameter is positional-only when it must be supplied by position and cannot be passed as a keyword argument. The slash / placed after the last positional-only parameter marks the boundary. Everything before the slash is positional-only; everything after it can be passed either way unless further restricted.
def divide(a, b, /): return a / b
Calling divide(10, 2) works, but divide(a=10, b=2) raises a TypeError. The slash is part of the function definition syntax; calls that try to use a keyword for a positional-only parameter fail at runtime.
Why Use Positional-Only Parameters?
The primary motivation is API design. When a parameter's name carries no semantic meaning to the caller, forcing positional arguments prevents callers from depending on a name that might change later. For example, a function that accepts two coordinates could be defined as def point(x, y, /). Callers must write point(3, 4) instead of point(x=3, y=4). This keeps the function's interface stable because parameter names are not part of the public contract.
Another reason is to allow future parameter renames without breaking existing callers. If a function is defined as def connect(host, port, /), you can later rename host to server without worrying that callers used host= in their code. For callers, the positional-only marker makes the parameter name an implementation detail.
Syntax and Ordering Rules
The slash must appear after all positional-only parameters. You can combine positional-only parameters with regular parameters and keyword-only parameters. The order is strict: positional-only parameters first, then slash, then positional-or-keyword parameters, then an asterisk * for keyword-only parameters.
def func(a, b, /, c, d, *, e, f): pass
Here, a and b are positional-only; c and d can be passed either way; e and f must be keyword-only. This ordering is enforced by the Python parser. Putting the slash after the * marker or after a keyword-only parameter is a syntax error.
Comparison With Keyword-Only Parameters
Keyword-only parameters are the opposite: they must be passed by name. They are declared after an asterisk *. The two mechanisms serve different purposes and can coexist in the same signature.
| Feature | Positional-only | Keyword-only |
|---|---|---|
| Syntax marker | / after the last positional-only param | * before the first keyword-only param |
| Call style | Must be passed by position | Must be passed by keyword |
| Parameter name | Not part of public API | Part of public API |
| Typical use | Internal implementation details | Optional configuration with clear names |
Common Use Cases and Built-in Examples
Python's standard library uses positional-only parameters in several built-in functions. For instance, len(obj) cannot be called as len(obj=some_list). Similarly, range(1, 10) cannot be called with keyword arguments. These functions were designed before the syntax was added, but the behavior is equivalent to using / in their definitions.
When you write your own library, positional-only parameters are useful for low-level helpers where the argument order is natural and the names would only add noise. For example, a matrix multiplication function matmul(a, b, /) makes it clear that the order matters and that the names a and b are not meant to be used externally.
Edge Cases and Common Mistakes
A frequent mistake is forgetting the slash and then wondering why a keyword call works. Without the slash, all parameters are positional-or-keyword by default. Adding the slash changes the behavior, so you must be explicit.
Another common error is misplacing the slash. For example, def func(*, a, /): raises a SyntaxError because the slash cannot appear after the asterisk. The correct order is to place the slash before the * marker.
You also cannot reuse a parameter name in the same function definition. Even though a positional-only parameter's name is not usable as a keyword by callers, it is still a name in the function body, so duplicate names cause a SyntaxError.
Maintainability and API Evolution
Positional-only parameters make it easier to evolve a function's signature without breaking existing callers. If a function is already called with positional arguments, adding a slash in the definition does not change how callers pass arguments; they still use positions. However, it prevents new callers from using keyword names, giving you the freedom to rename parameters later.
When designing a public API, decide whether parameter names are part of the contract. If they are not, mark them as positional-only. This is especially useful for functions with many parameters where the order is intuitive.
Compatibility With Python Versions
The positional-only parameter syntax was introduced in Python 3.8. If you are targeting Python 3.7 or earlier, this syntax will raise a SyntaxError. If you need to support older versions, you cannot use / in function definitions. You could simulate the behavior with *args and manual argument parsing, but that is less readable and more error-prone. For modern codebases, the slash is the cleanest way to enforce positional-only arguments.