<p>给出:</p>
<pre><code>def foo(a, b=2, *args, **kwargs): pass
</code></pre>
<p><code>b</code>不是一个只包含关键字的参数-它只是一个参数,参数可以是位置的或命名的,但是有一个默认值。不可能将任何值传递到<code>args</code>中,并且在建议的签名中忽略按顺序传递<code>b</code>或传递<code>b</code>。你知道吗</p>
<p>这个签名是有意义的,而且非常明确-可以传递0到n个位置参数,但是如果传递2个或更多,则第二个参数将被分配给“b”,故事结束。
如果传递0个位置参数,仍然可以将值作为命名参数赋给“a”或“b”,但尝试类似于:<code>foo(0, 1, 2, a=3, b=4)</code>的操作将失败,因为尝试将多个值传递给两个参数。你知道吗</p>
<p>其中:</p>
<pre><code>def foo(a, *args, b=2, **kwargs): pass
</code></pre>
<p>这也是一种明确的情况:第一个位置参数指向“a”,其他参数指向“args”,您只能将一个值作为命名参数传递给“b”。你知道吗</p>
<p>python3.8附带的签名定义中新的<code>/</code>语法为这一点提供了更大的灵活性,允许要求将“a”和“b”作为仅位置参数传递。同样,没有含糊不清的地方:</p>
<pre><code>def foo(a, b=2, /, *args, **kwargs): pass
</code></pre>
<p>这种新语法有一个奇怪的地方:一个是<em>允许</em>将命名参数传递给“A”和“b”,但命名参数将作为键/值对出现在“kwargs”中,而局部变量“A”和“b”将被分配仅位置参数:</p>
<pre><code>def foo(a, b=2, /, *args, **kwargs):
print(a, b, args, kwargs)
...
In [9]: foo(1, 2, a=3, b=4)
1 2 () {'a': 3, 'b': 4}
</code></pre>
<p>而对于传统语法,您询问-<code>def foo(a, b=2, *args, **kwargs):</code>-如果尝试了,就会得到一个TypeError:</p>
<pre><code>In [11]: foo(1,2, a=3, b=4)
-
TypeError Traceback (most recent call last)
<ipython-input-11-d002c7717dba> in <module>
> 1 foo(1,2, a=3, b=4)
TypeError: foo() got multiple values for argument 'a'
</code></pre>