擅长:python、mysql、java
<p>虽然大多数答案都是这样说的,例如</p>
<pre><code>def f(**kwargs):
foo = kwargs.pop('foo')
bar = kwargs.pop('bar')
...etc...
</code></pre>
<p>是“相同的”</p>
<pre><code>def f(foo=None, bar=None, **kwargs):
...etc...
</code></pre>
<p>这不是真的。在后一种情况下,<code>f</code>可以称为<code>f(23, 42)</code>,而前一种情况只接受命名参数<strong>而不接受位置调用。通常,您希望允许调用者具有最大的灵活性,因此第二种形式(正如大多数答案断言的那样)更可取:但情况并非总是如此。当您接受许多可选参数(通常只有少数参数被传递)时,这可能是一个很好的主意(避免在您的调用站点发生意外和无法读取的代码!)强制使用命名参数<code>threading.Thread</code>就是一个例子。第一种形式是如何在Python 2中实现它。</p>
<p>这个习惯用法非常重要,以至于在Python 3中,它现在有了特殊的支持语法:签名中单个<code>*</code>之后的每个参数都只是关键字,也就是说,不能作为位置参数传递,而只能作为命名参数传递。因此,在Python 3中,可以将上面的代码编写为:</p>
<pre><code>def f(*, foo=None, bar=None, **kwargs):
...etc...
</code></pre>
<p>实际上,在Python 3中,您甚至可以使用仅关键字的参数,这些参数<em>不是可选的(没有默认值的参数)。</p>
<p>然而,Python2还有很长的生产寿命,因此最好不要忘记那些让您在Python2中实现Python3语言直接支持的重要设计思想的技术和习惯用法!</p>