MikeL
MikeL

Reputation: 2459

Which exception should be raised on unknown keyword arguments?

In Python, which exception should be raised when an unknown keyword argument is passed to the function? Should it be SyntaxError? I saw that Python itself raises TypeError, but I am not sure why.

For example:

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

Upvotes: 1

Views: 1459

Answers (2)

MisterMiyagi
MisterMiyagi

Reputation: 50076

The appropriate error for unexpected or missing arguments is 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'

While the concrete type of a function is just function, Python semantically uses the common function type model in which the type of a function is its signature, i.e. Parameters -> Result. For example, the function

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

has the type (a: Any, b: Any) -> Any. As far as types are concerned, it is exchangeable with any other function of the same signature. This is codified by Python's optional static type support as well.

Calling a function means supplying matching Parameters. This uses Python's rules for matching arguments to parameters, e.g. add(b=3, a=1) still matches add(a: Any, b: Any).

A call with incompatible signature, e.g. add(1, 2, 3), means a function of different type is expected at the call site, e.g. (:Any, :Any, :Any) -> Any in this case. This means the type/signature of the call and the function do not match. Thus, TypeError is appropriate.

Upvotes: 4

MatsLindh
MatsLindh

Reputation: 52802

It'd probably be most appropriate to do the same as what Python itself does, which is that it raises a TypeError exception:

>>> 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'

A TypeError is also raised if you give more positional arguments than what the function supports, which also indicates that TypeError describes this kind of error the best (and is what you'd expect from Python itself).

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.

Upvotes: 1

Related Questions