TIL

The <code>/</code> and <code>*</code> syntax in Python function parameters

def foo(arg1, /, arg2, *, arg3):
    print(arg1, arg2, arg3)

Have you seen this syntax in Python functions? Let's unpack it:

  • Parameters listed before the / parameter are positional-only1.
  • Parameters after the * parameter are keyword-only2.
  • Parameters in between can be either positional or keyword-only.

Using this can be especially helpful if you provide your code as a shared library. It allows you to maintain control over how your function is called, in case you update the argument list in the future.

An example:

def calculate(x: int, y: int, /, *, method: str) -> None:
    if method != "multiply":
        raise ValueError("This calculator supports only multiplication. 🫣")
    print(f"{x} × {y} = {x * y}")
>>> calculate(1, 2, 'multiply')
TypeError: calculate() takes 2 positional arguments but 3 were given

>>> calculate(x=2, y=3, method='multiply')
TypeError: calculate() got some positional-only arguments passed as keyword arguments: 'x, y'

>>> calculate(1, 2, 3, method='multiply')
TypeError: calculate() takes 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given

>>> calculate(2, 3, method="multiply")
2 × 3 = 6