在Python中使用**kwargs的正确方法

2024-03-28 15:36:27 发布

您现在位置:Python中文网/ 问答频道 /正文

当谈到默认值时,在Python中使用**kwargs的正确方法是什么?

kwargs返回一个字典,但是设置默认值的最佳方法是什么,还是有一个?我应该把它当作字典来查吗?使用get函数?

class ExampleClass:
    def __init__(self, **kwargs):
        self.val = kwargs['val']
        self.val2 = kwargs.get('val2')

一个简单的问题,但我找不到好的资源。人们用我见过的不同的方式来编写代码,很难知道该用什么。


Tags: 方法函数代码selfget字典initdef
3条回答

我建议这样做

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中,它现在有了特殊的支持语法:签名中单个*之后的每个参数都只是关键字,也就是说,不能作为位置参数传递,而只能作为命名参数传递。因此,在Python 3中,可以将上面的代码编写为:

def f(*, foo=None, bar=None, **kwargs):
    ...etc...

实际上,在Python 3中,您甚至可以使用仅关键字的参数,这些参数不是可选的(没有默认值的参数)。

然而,Python2还有很长的生产寿命,因此最好不要忘记那些让您在Python2中实现Python3语言直接支持的重要设计思想的技术和习惯用法!

对于不在字典中的键,可以将默认值传递给get()

self.val2 = kwargs.get('val2',"default value")

但是,如果计划使用具有特定默认值的特定参数,为什么不首先使用命名参数?

def __init__(self, val2="default value", **kwargs):

相关问题 更多 >