*(单星)和/(斜杠)作为独立参数有什么作用?

What do * (single star) and / (slash) do as independent parameters?

在下面的函数定义中,*/是什么意思?

def func(self, param1, param2, /, param3, *, param4, param5):
     print(param1, param2, param3, param4, param5)

注意:不要误认为 *args | 中的单|双星号 | **kwargs (solved here)

docs 中所述,斜杠仅用于位置参数,如文档所述:

There is a new function parameter syntax / to indicate that some function parameters must be specified positionally and cannot be used as keyword arguments. This is the same notation shown by help() for C functions annotated with Larry Hastings’ Argument Clinic tool.

对于星号,它在 docs 中提到:

For a parameter with a default value, the corresponding argument may be omitted from a call, in which case the parameter’s default value is substituted. If a parameter has a default value, all following parameters up until the “*” must also have a default value — this is a syntactic restriction that is not expressed by the grammar.


def func(self, param1, param2, /, param3, *, param4, param5):
     print(param1, param2, param3, param4, param5)

所以调用它的方法是:

obj.func(10, 20, 30, param4=50, param5=60)

并且:

obj.func(10, 20, param3=30, param4=50, param5=60)

有一个new function parameter syntax/表示有些函数参数必须按位置指定,不能作为关键字参数。[这是新的在 Python 3.8]

文档指定了 positional-only parameters

的一些用法 cases/benefits
  1. It allows pure Python functions to fully emulate behaviors of existing C coded functions. For example, the built-in pow() function does not accept keyword arguments:

    def pow(x, y, z=None, /):
        "Emulate the built in pow() function"
        r = x ** y
        return r if z is None else r%z
    
  2. Another use case is to preclude keyword arguments when the parameter name is not helpful. For example, the builtin len() function has the signature len(obj, /). This precludes awkward calls such as:

    len(obj='hello')  # The "obj" keyword argument impairs readability
    
  3. A further benefit of marking a parameter as positional-only is that it allows the parameter name to be changed in the future without risk of breaking client code. For example, in the statistics module, the parameter name dist may be changed in the future. This was made possible with the following function specification:

    def quantiles(dist, /, *, n=4, method='exclusive')
        ...
    

其中 * 用于强制 caller to use named arguments. This is 命名参数的用例之一。

所以,给定方法,

def func(self, param1, param2, /, param3, *, param4, param5):
     print(param1, param2, param3, param4, param5)

必须用

调用
obj.func(10, 20, 30, param4=50, param5=60)

obj.func(10, 20, param3=30, param4=50, param5=60)

  1. param1,param2必须指定positionally.
  2. param3 可以用 positional or keyword.
  3. 调用
  4. param4param5 必须使用 keyword 参数调用。

演示:

>>> class MyClass(object):
...     def func(self, param1, param2, /, param3, *, param4, param5):
...         return param1, param2, param3, param4, param5
...
>>> obj = MyClass()
>>>
>>> assert obj.func(10, 20, 30, param4=40, param5=50), obj.func(
...     10, 20, param3=30, param4=40, param5=50
... )