Chapter 4: More functions

Positional-only and keyword-only arguments

face Josiah Wang

Here is a more advanced Python feature for passing arguments.

You can actually force your caller to use keyword arguments. In the following example, there is an asterisk (*) in the parameter before d in Line 1. Everything after the * (from d onwards) must be passed as keyword arguments and not positional arguments (Line 4).

1
2
3
4
5
def do_something(a, b, c, *, d=0, e=0):
    print(a, b, c, d, e)

do_something(1, 3, 5, d=4, e=2) # this works!
do_something(1, 3, 5, 4, 2) # this does not work!

Similarly, you can also force your caller to use positional arguments (this is only available from Python 3.8 onwards). In the following example, there is a slash (/) in the parameter before c in Line 1. So everything before the / must be passed as positional arguments and not keyword arguments (Line 4-5). Also, whatever parameters between / and * (c in this case) can be passed as either positional or keyword arguments (Line 4-5).

1
2
3
4
5
6
def do_something(a, b, /, c, *, d=0, e=0):
    print(a, b, c, d, e)

do_something(1, 3, 5, d=4, e=2) # this works!
do_something(1, 3, c=5, d=4, e=2) # this works!
do_something(a=1, b=3, c=5, d=4, e=2) # this does not work!

You will unlikely be using these features much, but again it’s something good to know for when you do need them!

For those interested in reading further (not essential), PEP 3102 explains the rationale for introducing the keyword-only parameters, while PEP 570 has more detailed rationales and applications for using position-only parameters.