In Python, function parameters can be Positional-Only, Positional-or-Keyword, or Keyword-Only.
Let’s consider all three cases in the example function f
:
def f(pos1, pos2, /, pos_or_kwd1, pos_or_kwd2=None, *, kwd1, kwd2):
"""
pos1, pos2 - are Positional-Only
pos_or_kwd1, pos_or_kwd2 - are Positional-or-Keyword
kwd1, kwd2 - are Keyword-Only
"""
pass
The rules for defining these parameters are straightforward:
- Everything before the
/
symbol is Positional-Only parameters. - Everything after the
*
symbol is Keyword-Only parameters. - What’s between
/
and*
can be passed as both Positional and Keyword. - If there is no
/
symbol, there are no Positional-Only parameters. - If there is no
*
symbol, there are no Keyword-Only parameters. - If
/
and*
are not present, arguments can be passed to a function by position or by keyword.
Here are some valid calls to this function:
f(1, 2, 'a', kwd1='c', kwd2='d')
f(1, 2, 'a', 'b', kwd1='c', kwd2='d')
f(1, 2, 'a', pos_or_kwd2='b', kwd1='c', kwd2='d')
f(1, 2, pos_or_kwd1='a', kwd1='c', kwd2='d')
Note that the first two arguments are Positional-Only, and we cannot pass them as pos1=1
.
Meanwhile, the last two arguments are Keyword-Only, and we cannot omit the use of the name when passing the argument value.
Here are some invalid calls to the function f
that will raise an exception:
f(1, 2, 'a', 'b', 'c', kwd2='d') # raises...
# TypeError: f() takes from 3 to 4 positional arguments but 5 positional arguments (and 1 Keyword-Only argument) were given
f(pos1=1, pos2=2, pos_or_kwd1='a', kwd1='c', kwd2='d') # raises...
# TypeError: f() got some Positional-Only arguments passed as keyword arguments: 'pos1, pos2'
The logic around optional values for Positional-Only parameters remains the same as for Positional-or-Keyword parameters. For example:
def f(pos1, pos2=2, /, pos_or_kwd1='a', *, kwd1, kwd2):
pass
Once a Positional-Only parameter is specified with a default, the following Positional-Only and Positional-or-Keyword parameters need to have defaults as well.
As guidance, use Positional-Only if names do not matter or have no meaning, and there are only a few arguments that will always be passed in the same order. Use Keyword-Only when names have meaning, and the function definition is more understandable by being explicit with names.
For more information, refer to PEP 3102 (Keyword-Only Arguments) and PEP 570 (Python Positional-Only Parameters).