Python 解包参数:只有命名参数可以跟在 *expression 之后
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12720450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unpacking arguments: only named arguments may follow *expression
提问by dreeves
The following works beautifully in Python:
以下内容在 Python 中运行良好:
def f(x,y,z): return [x,y,z]
a=[1,2]
f(3,*a)
The elements of aget unpacked as if you had called it like f(3,1,2)and it returns [3,1,2]. Wonderful!
aget的元素被解压,就像你调用它一样f(3,1,2),它返回[3,1,2]. 精彩的!
But I can't unpack the elements of ainto the firsttwo arguments:
但我无法将 的元素解压a到前两个参数中:
f(*a,3)
Instead of calling that like f(1,2,3), I get "SyntaxError: only named arguments may follow *expression".
f(1,2,3)我没有像这样调用它,而是得到“SyntaxError:只有命名参数可以跟在 *expression 之后”。
I'm just wondering why it has to be that way and if there's any clever trick I might not be aware of for unpacking arrays into arbitrary parts of argument lists without resorting to temporary variables.
我只是想知道为什么必须这样,如果有任何聪明的技巧我可能不知道将数组解包到参数列表的任意部分而不诉诸临时变量。
采纳答案by dreeves
As Raymond Hettinger's answer points out, this may changehas changed in Python 3 and here is a related proposal, which has been accepted.
Especially related to the current question, here's one of the possible changes to that proposal that was discussed:
正如雷蒙德·赫廷格 (Raymond Hettinger) 的回答所指出的,这可能会在 Python 3 中发生变化,这里有一个相关的提案,该提案已被接受。特别是与当前问题相关,以下是对该提案进行的可能更改之一:
Only allow a starred expression as the last item in the exprlist. This would simplify the unpacking code a bit and allow for the starred expression to be assigned an iterator. This behavior was rejected because it would be too surprising.
只允许带星号的表达式作为表达式列表中的最后一项。这将稍微简化解包代码,并允许为带星号的表达式分配一个迭代器。这种行为被拒绝了,因为这太令人惊讶了。
So there are implementation reasons for the restriction with unpacking function arguments but it is indeed a little surprising!
所以解包函数参数的限制是有实现原因的,但确实有点令人惊讶!
In the meantime, here's the workaround I was looking for, kind of obvious in retrospect:
与此同时,这是我正在寻找的解决方法,回想起来很明显:
f(*(a+[3]))
回答by Raymond Hettinger
It doesn't have tobe that way. It was just rule that Guido found to be sensible.
它并不必须是这样。Guido 认为这是明智的规则。
In Python 3, the rules for unpacking have been liberalized somewhat:
在 Python 3 中,解包规则有所放宽:
>>> a, *b, c = range(10)
>>> a
0
>>> b
[1, 2, 3, 4, 5, 6, 7, 8]
>>> c
9
Depending on whether Guido feels it would improve the language, that liberalization could also be extended to function arguments.
取决于 Guido 是否认为它会改进语言,自由化也可以扩展到函数参数。
See the discussion on extended iterable unpackingfor some thoughts on why Python 3 changed the rules.
有关Python 3 为何更改规则的一些想法,请参阅有关扩展可迭代解包的讨论。
回答by inspectorG4dget
fis expecting 3 arguments (x, y, z, in that order).
f需要 3 个参数(按顺序x, y, z, )。
Suppose L = [1,2]. When you call f(3, *L), what python does behind the scenes, is to call f(3, 1, 2), without really knowing the length of L.
假设L = [1,2]。当您调用 时f(3, *L),python 在幕后所做的就是调用f(3, 1, 2),而无需真正知道L.
So what happens if Lwas instead [1,2,3]?
那么如果Lwas会发生什么[1,2,3]呢?
Then, when you call f(3, *L), you'll end up calling f(3,1,2,3), which will be an error because fis expecting exactly 3 arguments and you gave it 4.
然后,当您调用 时f(3, *L),您最终会调用f(3,1,2,3),这将是一个错误,因为f期望正好有 3 个参数,而您给了它 4 个。
Now, suppose L=[1,2]1. Look at what happens when you callf`:
现在,假设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
Now, you implicitly know when you call f(*L, 3)that 3 will be assigned to z, but python doesn't know that. It only knows that the last jmany elements of the input to fwill be defined by the contents of L. But since it doesn't know the value of len(L), it can't make assumptions about whether f(*L,3)would have the correct number of arguments.
现在,您隐含地知道何时调用f(*L, 3)3 将被分配给z,但是 python 不知道。它只知道j输入 to的最后许多元素f将由 的内容定义L。但是由于它不知道 的值len(L),因此无法假设是否f(*L,3)具有正确数量的参数。
This however, is not the case with f(3,*L). In this case, python knows that all the arguments EXCEPT the first one will be defined by the contents of L.
然而,情况并非如此f(3,*L)。在这种情况下,python 知道除了第一个参数之外的所有参数都将由L.
But if you have named arguments f(x=1, y=2, z=3), then the arguments being assigned to by name will be bound first. Only then are the positional arguments bound. So you do f(*L, z=3). In that case, zis bound to 3first, and then, the other values get bound.
但是如果你有命名参数f(x=1, y=2, z=3),那么按名称分配的参数将首先被绑定。只有这样,位置参数才会被绑定。所以你这样做f(*L, z=3)。在这种情况下,z首先绑定到3,然后绑定其他值。
Now interestingly, if you did f(*L, y=3), that would give you an error for trying to assign to ytwice (once with the keyword, once again with the positional)
现在有趣的是,如果你这样做了f(*L, y=3),那会给你一个错误,试图分配给y两次(一次是关键字,一次是位置)
Hope this helps
希望这可以帮助
回答by strawbot
Nice. This also works for tuples. Don't forget the comma:
好的。这也适用于元组。不要忘记逗号:
a = (1,2)
f(*(a+(3,)))
回答by Antti Haapala
Thanks to the PEP 448 - Additional Unpacking Generalizations,
感谢PEP 448 - Additional Unpacking Generalizations,
f(*a, 3)
is now accepted syntax starting from Python 3.5. Likewise you can use the double-star **for keyword argument unpacking anywhere and either one can be used multiple times.
是目前公认的语法在Python 3.5开始。同样,您可以在**任何地方使用双星进行关键字参数解包,并且任何一个都可以多次使用。
回答by Jianzhong He
You can use f(*a, z=3)if you use f(*a, 3), it do not know how to unpack the parameter for you provided 2 parameters and 2 is the second.
您可以使用f(*a, z=3),如果你使用f(*a, 3),它不知道如何解压参数为您提供了2个参数,2是第二个。

