我有以下功能:
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_index
或end_index
。其他任何东西都会引发错误,即使与有效的混合也是如此。什么是食谱配方,以确保只接受start_index
或end_index
?是的,我正在寻找食谱配方,但我不确定如何搜索它。我不确定使用if-elif-else
结构是否正确。
答案 0 :(得分:12)
为什么你需要**kwargs
?刚
def foo(start_index=None, end_index=None):
并且Python将为您执行所有验证。
答案 1 :(得分: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
dict中是否存在密钥可以准确区分这些情况。 (另一种方法是创建object
子类的实例,其唯一目的是成为该特定函数的特定参数的默认值。
答案 2 :(得分: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
但所有这些都是复制内置功能的复杂而缓慢的方法。除非你真的需要,否则不要这样做。
答案 3 :(得分:0)
无论如何从dict获取密钥就像使用.get
一样简单。
kwargs.get('WIDTH',500)
这样一来,如果它没有找到WIDTH作为密钥就可以得到500.