47

以下在 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)

我没有调用 like f(1,2,3),而是得到“SyntaxError: only named arguments may follow *expression”。

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

4

6 回答 6

37

正如 Raymond Hettinger 的回答所指出的那样,这可能在 Python 3 中发生了变化,这是一个相关的提案,已被接受。特别是与当前问题相关,以下是所讨论的提案的可能更改之一:

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

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

与此同时,这是我一直在寻找的解决方法,回想起来有点明显:

f(*(a+[3]))
于 2012-10-10T23:31:45.830 回答
12

不一定那样。Guido 认为这只是规则。

在 Python 3 中,解包的规则有所放宽:

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

根据 Guido 是否认为它会改进语言,这种自由化也可以扩展到函数参数。

有关Python 3 更改规则的一些想法,请参阅关于扩展可迭代解包的讨论。

于 2012-10-04T05:07:03.800 回答
12

感谢PEP 448 - Additional Unpacking Generalizations

f(*a, 3)

现在接受从 Python 3.5 开始的语法。同样,您可以在任何地方使用双星**进行关键字参数解包,并且可以多次使用其中任何一个。

于 2015-09-22T13:25:09.490 回答
4

f期望 3 个参数(x, y, z, 按此顺序)。

假设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 callf`:

>>> 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输入 to 的最后许多元素f将由L. 但由于它不知道 的值len(L),它无法假设是否f(*L,3)会有正确数量的参数。

然而,情况并非如此f(3,*L)。在这种情况下,python 知道除了第一个参数之外的所有参数都将由L.

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

现在有趣的是,如果你这样做了f(*L, y=3),那会给你一个尝试分配y两次的错误(一次是关键字,一次是位置)

希望这可以帮助

于 2012-10-04T05:09:29.543 回答
3

用的f(*a, z=3)话可以用f(*a, 3),不知道怎么解压参数给你提供2个参数,2是第二个。

于 2018-02-01T07:34:10.660 回答
2

好的。这也适用于元组。不要忘记逗号:

a = (1,2)
f(*(a+(3,)))
于 2013-08-29T20:43:30.833 回答