解包参数:只有命名参数可以跟*表达式

时间:2012-10-04 04:52:38

标签: python arrays arguments

以下在Python中非常有效:

def f(x,y,z): return [x,y,z]

a=[1,2]

f(3,*a)

a的元素得到解压缩,就好像你像f(3,1,2)一样调用它并返回[3,1,2]。精彩!

但我无法将a的元素解压缩到第一个两个参数中:

f(*a,3)

而不是像f(1,2,3)那样调用,我得到“SyntaxError:只有命名参数可以跟*表达式”。

我只是想知道为什么它必须是这样的,如果有任何聪明的技巧我可能不会意识到将数组解压缩到参数列表的任意部分而不诉诸临时变量。

6 个答案:

答案 0 :(得分:32)

正如Raymond Hettinger的回答所指出的,这个可能会改变在Python 3和here is a related proposal中已经被接受了。 特别是与当前问题相关,这是对所讨论的提案的可能变更之一:

  

仅允许星号表达式作为exprlist中的最后一项。这将简化   稍微解压缩代码并允许为已加星标的表达式分配迭代器。这个   行为被拒绝了,因为这太令人惊讶了。

因此有解包函数参数限制的实现原因,但确实有点令人惊讶!

与此同时,这是我正在寻找的解决方法,回顾过去很明显:

f(*(a+[3]))

答案 1 :(得分:12)

感谢PEP 448 - Additional Unpacking Generalizations

f(*a, 3)

now accepted syntax starting from Python 3.5。同样,您可以在任意位置使用双星**关键字参数解压缩,并且可以多次使用其中一个。

答案 2 :(得分:11)

不必那样。 Guido认为这是合理的规则。

在Python 3中,解包的规则已经有所自由:

>>> a, *b, c = range(10)
>>> a
0
>>> b
[1, 2, 3, 4, 5, 6, 7, 8]
>>> c
9

根据Guido是否认为它会改善语言,自由化也可以扩展到功能论点。

有关Python 3改变规则的原因的一些想法,请参阅有关extended iterable unpacking的讨论。

答案 3 :(得分:4)

f期待3个参数(xyz,按顺序排列。)

假设L = [1,2]。当你调用f(3, *L)时,python在幕后做什么就是调用f(3, 1, 2),而不知道L的长度。

那么如果L改为[1,2,3]会发生什么?

然后,当您致电f(3, *L)时,您最终会调用f(3,1,2,3),这将是一个错误,因为f正好期待3个参数而您给它4个。

现在,假设L=[1,2]1. Look at what happens when you call f`:

>>> f(3,*L) # works fine
>>> f(*L) # will give you an error when f(1,2) is called; insufficient arguments

现在,您隐含地知道何时调用f(*L, 3)将3分配给z,但python不知道。它只知道j输入的最后f个元素将由L的内容定义。但由于它不知道len(L)的值,因此无法假设f(*L,3)是否具有正确数量的参数。

然而,f(3,*L)并非如此。在这种情况下,python知道除{1}之外的所有参数都将由L的内容定义。

但是如果你有参数f(x=1, y=2, z=3),那么按名称分配的参数将首先被绑定。只有这样才能限制位置参数。所以你做f(*L, z=3)。在这种情况下,z首先绑定到3,然后其他值绑定。

现在有趣的是,如果您执行f(*L, y=3),那么尝试分配给y两次会产生错误(一次使用关键字,再次使用位置)

希望这有帮助

答案 4 :(得分:2)

尼斯。这也适用于元组。不要忘记逗号:

a = (1,2)
f(*(a+(3,)))

答案 5 :(得分:1)

如果您使用f(*a, z=3),则可以使用f(*a, 3),它不知道如何解压缩参数,因为您提供了2个参数而2是第二个参数。