No, it is not generally sensible to use the PEP-570 positional-only arguments that are available since Python 3.8.
When you define a function def foo(a, b)
,
then you can use the arguments as either positional or named arguments. All of these are equivalent:
foo(1, 2)
foo(1, b=2)
foo(a=1, b=2)
foo(b=2, a=1)
But sometimes, you want keyword-only or positional-only arguments.
By using a *
, you can force keyword-only arguments.
When we have def foo(*, a, b)
then only foo(a=1, b=2)
or foo(b=2, a=1)
invocations are allowed.
By using a /
, you can force positional-only arguments.
When we have def foo(a, b, /)
then only foo(1, 2)
invocation is allowed.
So what def something(self, /, some_arg)
tells us is that self
can never be passed as a keyword argument. Does this make sense? Kind of yes, but this is not really important.
You see /
in a lot of built-in functions because these are often implemented in C code, and they don't want to support keyword arguments for efficiency and simplicity reasons.
For maintainability, it is usually a very good idea to allow keyword arguments, or even to force keyword-only arguments. In contrast, positional-only arguments make most sense in these two cases:
You don't want to expose your parameter names as part of the public API. For example, you don't want that people can call some_function(123)
as some_function(internal_name=123)
because then renaming the parameter would be an API-breaking change. This doesn't really matter for methods since the self
parameter is passed implicitly.
You have profiled your application and the data indicates that calls to this function are performance-critical. Calls with positional-only arguments are faster on recent Python versions. But don't start using positional-only arguments everywhere as a premature optimization!