在Python中正确使用**kwargs的方法
在Python中,使用**kwargs
时,怎样设置默认值才是正确的呢?
kwargs
会返回一个字典,但设置默认值的最佳方法是什么呢?或者说有没有最佳方法?我是不是应该直接把它当成字典来用?还是用get
函数更好?
class ExampleClass:
def __init__(self, **kwargs):
self.val = kwargs['val']
self.val2 = kwargs.get('val2')
我看到的代码中,大家的做法各不相同,真不知道该用哪种方式。
14 个回答
我建议可以这样做
def testFunc( **kwargs ):
options = {
'option1' : 'default_value1',
'option2' : 'default_value2',
'option3' : 'default_value3', }
options.update(kwargs)
print options
testFunc( option1='new_value1', option3='new_value3' )
# {'option2': 'default_value2', 'option3': 'new_value3', 'option1': 'new_value1'}
testFunc( option2='new_value2' )
# {'option1': 'default_value1', 'option3': 'default_value3', 'option2': 'new_value2'}
然后你可以随意使用这些值
dictionaryA.update(dictionaryB)
这个操作是把 dictionaryB
的内容添加到 dictionaryA
中,如果有重复的键,就会覆盖掉原来的值。
虽然大多数回答都说,比如说:
def f(**kwargs):
foo = kwargs.pop('foo')
bar = kwargs.pop('bar')
...etc...
是“相同的”,
def f(foo=None, bar=None, **kwargs):
...etc...
但这并不完全正确。在后者的情况下,f
可以像这样调用:f(23, 42)
,而前者只接受命名参数,不支持位置参数。通常你希望给调用者最大的灵活性,因此大多数回答认为第二种形式更好,但这并不总是适用。当你接受很多可选参数,而通常只有少数几个会被传递时,强制使用命名参数可能是个好主意(这样可以避免意外和让代码难以阅读的情况!)——threading.Thread
就是一个例子。第一种形式是在 Python 2 中实现这一点的方法。
这个用法非常重要,以至于在 Python 3 中,它现在有了特别的支持语法:在 def
定义中,单个 *
后面的每个参数都是仅限关键字的,也就是说,不能作为位置参数传递,只能作为命名参数传递。所以在 Python 3 中,你可以这样写:
def f(*, foo=None, bar=None, **kwargs):
...etc...
实际上,在 Python 3 中,你甚至可以有那些不是可选的关键字参数(没有默认值的参数)。
然而,Python 2 仍然有很长的使用寿命,所以最好不要忘记那些让你在 Python 2 中实现重要设计思想的技巧和用法,这些在 Python 3 中得到了直接支持!
你可以给get()
方法传一个默认值,这样如果字典里没有你要找的键,就会返回这个默认值:
self.val2 = kwargs.get('val2',"default value")
不过,如果你打算用某个特定的参数和特定的默认值,那为什么不直接使用命名参数呢?
def __init__(self, val2="default value", **kwargs):