This is just an example, this mostly applies to built-in functions such as range().
Although I also use it when the signature of a class is incompatible with its super class. e.g.
Also, using parameter hints would be faster than keyword arguments:
$ python -m timeit -s "f = lambda a, b, c: a + b + c" "f(1, 2, 3)" && python -m timeit -s "f = lambda a, b, c: a + b + c" "f(a=1, b=2, c=3)"
5000000 loops, best of 5: 69.5 nsec per loop # positional
5000000 loops, best of 5: 99.2 nsec per loop # keyword
Yes, I know this is pre-mature optimisation, but it would be as readable as keywords.
If you find that someone else’s interface is awkward because it uses positional-only arguments, make a wrapper.
For Python code, you can probably use the inspect module to automate this. It’s not trivial, though.
The problem is that built-ins don’t actually have names for those positional-only arguments, because they’re implemented in a context that doesn’t need names - the C code receives the arguments via the C API which has already stuffed them into a tuple, and assuming those arguments are unpacked into local variables in the C code, those names aren’t exposed anywhere (even in a debug build, they’d only be visible to a C debugger). So we can’t support something like range(step=2) “automatically”, because range doesn’t just reject passing the arguments by keyword - it doesn’t have any keywords to use.
I don’t really understand why. That doesn’t seem like a good way to signal the issue. But aside from that, __init__ and __new__ are special, because they’re concerned with object creation. Beyond that point, methods should uphold the Liskov Substitution Principle.