应该在未知关键字参数上引发哪个异常?

Which exception should be raised on unknown keyword arguments?

在Python中,当一个未知的关键字参数被传递给函数时应该引发哪个异常?应该是SyntaxError? I saw that Python itself raises TypeError,但我不确定为什么。

例如:

def add(**kwargs):
    a = kwargs.pop('a', 0.)
    b = kwargs.pop('b', 0.)

    if kwargs:
        # what to raise here?
        raise SyntaxError('Unknown keyword arguments: ' + list(kwargs.keys()))
        # or ? 
        # raise TypeError('Unknown keyword arguments: ' + list(kwargs.keys()))

    return a + b

最合适的做法可能与 Python 本身所做的相同,即引发 TypeError 异常:

>>> def f(a, b):
...   pass
...
>>> f(a=1, b=2, c=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'c'

如果您提供的位置参数多于函数支持的位置参数,也会引发 TypeError,这也表明 TypeError 最能描述此类错误(并且是您所期望的来自 Python 本身)。

Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch.

意外或缺少参数的适当错误是 TypeError

>>> def add(a, b=0.): ...
>>> add(a=3, c=5)
TypeError: add() got an unexpected keyword argument 'c'
>>> add(1, 2, 3)
TypeError: add() takes from 1 to 2 positional arguments but 3 were given
>>> add()
TypeError: add() missing 1 required positional argument: 'a'

虽然函数的具体类型只是function,但Python在语义上使用了通用的function type model,其中函数的类型是它的签名,即Parameters -> Result.例如,函数

def add(a, b): return a + b

具有类型 (a: Any, b: Any) -> Any。就类型而言,它可以与具有相同签名的任何其他功能交换。这也由 Python 的可选 static type support 编纂。

调用函数意味着提供匹配Parameters。这使用 Python 的规则来匹配参数,例如add(b=3, a=1) 仍然匹配 add(a: Any, b: Any).

签名不兼容的调用,例如add(1, 2, 3),表示调用站点需要 不同 类型的函数,例如(:Any, :Any, :Any) -> Any 在这种情况下。这意味着调用的 type/signature 和函数不匹配。因此,TypeError是合适的。