检测无效的关键字参数

5 投票
4 回答
3582 浏览
提问于 2025-04-16 22:48

我有一个这样的函数:

def foo(**kwargs):
  if not kwargs:
    # No keyword arguments? It's all right. Set defaults here...
  elif ('start_index' or 'end_index') in kwargs:
    # Do something here...
  else:
    # Catch unexpected keyword arguments
    raise TypeError("%r are invalid keyword arguments" % (kwargs.keys())

问题:

我想确保只有 start_indexend_index 这两个关键字参数是有效的。其他任何参数即使和有效的参数一起使用也会报错。我该怎么做才能确保只接受 start_indexend_index 呢?我想找一个简单的解决方案,但不知道怎么搜索。我也不确定使用 if-elif-else 结构是否是正确的方法。

4 个回答

1

如果你真的想用 **kwargs,我会这样写:

def foo(**kwargs):
    # Define default values for all keys
    args = {'start_index': 0, 'end_index': -1}

    # Get the keys passed in that aren't in args
    extraargs = set(kwargs) - set(args)
    if extraargs:
        raise TypeError("Invalid arguments: %s" % list(extraargs))

    # Overwrite the default values with the passed-in values
    args.update(kwargs)

    # Now, do stuff with the values in args

不过,这样做其实是个复杂又慢的方法,来重复一些内置的功能。除非你真的需要,不然最好别这么做。

13

为什么这里需要 **kwargs 呢?其实只要

def foo(start_index=None, end_index=None):

这样做,Python 就会自动帮你检查所有的有效性。

5

为了完整性,这里有一个替代方案,依然使用了 **kwargs

def foo(**kwargs):
  start_index = kwargs.pop('start_index', STARTINDEX_DEFAULT)
  end_index = kwargs.pop('end_index', ENDINDEX_DEFAULT)
  if kwargs:
    # Catch unexpected keyword arguments
    raise TypeError("%r are invalid keyword arguments" % (kwargs.keys())
  # Do something here...

但是,如果你不是特别需要,最好还是使用普通的带默认值的参数(就像Roman Bodnarchuk的回答里提到的那样)。

你可能需要这种方式的情况是,当你还想使用 *args,并且需要一种方法来区分关键字参数和任意位置参数。使用 **kwargs 这种方式可以强制关键字参数以关键字的形式传递;位置参数永远不会被放入 **kwargs 中。

另一个原因是这样可以让你真正区分默认参数和恰好是默认值的显式参数。通常,None 被用作参数的默认值,表示“这个参数不适用”,但有时候你实际上需要将 None 解释为其他东西,而不是默认值。在 **kwargs 字典中检查某个键的存在与否,可以准确区分这些情况。(另一种方法是创建一个 object 的子类实例,其唯一目的是作为特定函数特定参数的默认值)

撰写回答