**kwargs和默认参数

Ziz*_* Wu 2 python kwargs python-2.7

class Klass:
  def __init__(self, **kwargs):
    self.func(variable=True, **kwargs)

  def func(self, variable=True, **kwargs):
    print(variable)


if __name__ == '__main__':
  Klass(variable=False)
Run Code Online (Sandbox Code Playgroud)

我想知道为什么我会得到TypeError: func() got multiple values for keyword argument 'variable'.

我认为它应该打印,False因为我覆盖默认值为variableto False并传递kwargs.

Sha*_*ger 11

你不能两次传递相同的参数,并且variable=True, **kwargskwargs包含一个键时完全相同variable; 在这种情况下,你有效地进行了呼叫self.func(variable=True, variable=False),这显然是错误的.假设您不能variable作为单独的参数接收,例如:

def __init__(self, variable=True, **kwargs):
    self.func(variable, **kwargs)
Run Code Online (Sandbox Code Playgroud)

那么另一种方法是在kwargs dict自身中设置默认值:

def __init__(self, **kwargs):
    kwargs.setdefault('variable', True)  # Sets variable to True only if not passed by caller
    self.func(**kwargs)
Run Code Online (Sandbox Code Playgroud)

在Python 3.5中,通过PEP 448的其他拆包概括,您可以安全地将其排成一行:

def __init__(self, **kwargs):
    self.func(**{'variable': True, **kwargs})
Run Code Online (Sandbox Code Playgroud)

因为重复键在创建新键时是合法的dict(只保留最后一次出现的键),因此您可以创建dict具有唯一映射的全新键,然后立即将其解压缩.

  • 值得一提的是(假设 OP 不关心 Python 2)您可以执行 `def __init__(self, *, variable=True, **kwargs):`。这为您提供了第一个版本的优点(在签名中明确可见,而不是被迫通过 kwargs)而没有可能的缺点。(当然,如果能够在位置上传递它是你_想要_的,而不是你_想要避免的_,这根本不是缺点,而且你的第一个版本已经很完美了。) (2认同)