检测无效的关键字参数。

5

I have the following function:

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结构来实现。


你是否知道 ('start_index' or 'end_index') in kwargs 不会像你预期的那样工作? string1 or string2 会返回其中一个字符串(很可能是 string1),所以你的示例将 永远 不会检查 'end_index' in kwargs。类似于 for kw in ('start_index', 'end_index'): if kw in kwargs ... 的方式可以解决问题。 - Tobias Kienzler
4个回答

13

为什么你在这里需要**kwargs?只需

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

而 Python 会为您执行所有验证。


1
谢谢你提醒我这个问题。我忘记在我的问题中明确指出使用 **kwargs 是必要的。 - Kit

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子类的实例,其唯一目的是成为该特定函数的特定参数的默认值)


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

但是所有这些都是复制内置功能的复杂而缓慢的方式。除非你真的需要,否则不要这样做。


0
无论如何,从字典中获取键值都很容易,只需使用.get即可。

kwargs.get('WIDTH',500)

这样,如果没有找到 WIDTH 作为键,你就会得到 500。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接