如果我有以下功能:
def f(a,b,c,d):
print a,b,c,d
那么为什么会这样:
f(1,2,3,4)
f(*[1,2,3,4])
但不是这样:
f(*[1,2] , *[3,4])
f(*[1,2] , *[3,4])
^
SyntaxError: invalid syntax
编辑: 有关信息,最初的问题是替换函数包装器中的一个参数。我想替换输入的* args的给定成员并尝试类似:
def vectorize_pos(f,n=0):
'''
Decorator, vectorize the processing of the nth argument
:param f: function that dont accept a list as nth argument
'''
def vectorizedFunction(*args,**kwargs):
if isinstance(args[n],list):
return map(lambda x : f( *(args[:n]) , x , *(args[n+1,:]), **kwargs),args[n])
else:
return f(*args,**kwargs)
return vectorizedFunction
问题出现在那里。而且我知道还有其他方法可以做同样的事情,但只是想了解为什么解压缩一个序列有效但不是更多。
答案 0 :(得分:19)
因为,根据Function call syntax,这是参数列表的定义方式
argument_list ::= positional_arguments ["," keyword_arguments]
["," "*" expression] ["," keyword_arguments]
["," "**" expression]
| keyword_arguments ["," "*" expression]
["," keyword_arguments] ["," "**" expression]
| "*" expression ["," keyword_arguments] ["," "**" expression]
| "**" expression
因此,每个函数调用只能传递一个* expression
。
答案 1 :(得分:13)
从Python 3.5开始, 工作。
PEP 448在Python 3.5中实现。引用PEP,它允许,除其他外:
任意定位解包运营商:
>>> print(*[1], *[2], 3) 1 2 3 >>> dict(**{'x': 1}, y=2, **{'z': 3}) {'x': 1, 'y': 2, 'z': 3}
答案 2 :(得分:5)
您可以连接列表:
>>> f(*[1,2]+[3,4])
1 2 3 4
或使用itertools.chain
:
>>> from itertools import chain
>>> f(*chain([1,2], [3,4]))
1 2 3 4
答案 3 :(得分:5)
此会工作。
>>>def f(a,b,c,d):
print('hello') #or whatever you wanna do.
>>>f(1,2,*[3,4])
hello
不起作用的原因是Python使用this
实现了这一点一个列表解包,并且遵循语义,之后的任何参数必须是命名关键字参数(或通过 **传递命名关键字参数的dictonary)
通过对比,这可行。
>>>def f(a,b,c,k):
pass
>>>f(1,*[2,3],k=4)
答案 4 :(得分:4)
它没有用,因为它的语法无效 - 也就是说,它实际上并不是Python,尽管它看起来像。
Python 2函数签名中只允许使用一个已加星标的参数,它必须遵循任何位置参数并在任何关键字参数之前。类似地,只允许一个双星参数,它必须遵循签名中的所有关键字参数。如果您想要提交多个参数列表,则必须首先从它们创建一个列表。
在Python 3中,也可以单独使用星号来表示任何以下参数都是所谓的仅关键字参数,但我认为我们还不需要进入。
答案 5 :(得分:3)
这里的*
不是作为运营商。它更像是函数调用语法的一部分,它只允许某些有限的可能性。可以定义语言,以便你可以做你想做的事情(我已经完成了!),但这不是你做出的选择。
答案 6 :(得分:3)
这些可能有所帮助。请注意,类比是其他语言中可变数量的参数。这意味着一旦你说你要使用可变数量的参数,所有后面的参数都是该列表的一部分(类似于使用varargs的C或C ++)。
例如,f = [1,2,3,4,5]
def func(a, b, c, d)
print a, b, c, d
func(f) # Error 1 argument, 4 required
func(*f) # Error 5 arguments 4 required
http://www.python-course.eu/passing_arguments.php
可变长度参数
我们现在将介绍其中的功能 可以采用任意数量的参数。那些有一些 用C或C ++编程背景从varargs特性中知道这一点 这些语言。 Python中使用星号“*”来定义 可变数量的参数。星号字符必须在a之前 参数列表中的变量标识符。>>> def varpafu(*x): print(x) ... >>> varpafu() () >>> varpafu(34,"Do you like Python?", "Of course") (34, 'Do you like Python?', 'Of course') >>>
我们从前面的例子中学习,传递给的参数 varpafu()的函数调用是在元组中收集的,可以是元组 作为函数体内的“正常”变量x访问。如果 在没有任何参数的情况下调用该函数,x的值为a 空元组。
有时候,有必要使用位置参数后跟一个 函数定义中的任意数量的参数。这是 可能,但位置参数总是必须先于 任意参数。在下面的例子中,我们有一个位置 参数“city”, - 主要位置, - 总是必须的 给定,然后是任意数量的其他位置:
>>> def locations(city, *other_cities): print(city, other_cities) ... >>> locations("Paris") ('Paris', ()) >>> locations("Paris", "Strasbourg", "Lyon", "Dijon", "Bordeaux", "Marseille") ('Paris', ('Strasbourg', 'Lyon', 'Dijon', 'Bordeaux', 'Marseille')) >>>
http://docs.python.org/2.7/reference/expressions.html
如果语法*表达式出现在函数调用表达式中 必须评估为可迭代。处理此可迭代的元素 好像他们是额外的位置论点;如果有 位置参数x1,...,xN和表达式求值为a 序列y1,...,yM,这相当于具有M + N位置的调用 参数x1,...,xN,y1,...,yM。
这样做的结果是虽然*表达式语法可能 在一些关键字参数之后出现,它在之前被处理 关键字参数(和**表达式参数,如果有的话 - 见下文)。 所以:
>
>>> def f(a, b): ... print a, b ... >>> f(b=1, *(2,)) 2 1 >>> f(a=1, *(2,)) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: f() got multiple values for keyword argument 'a' >>> f(1, *(2,)) 1 2
关键字参数和*表达式语法都不常见 在同一个电话中使用,所以在实践中这种混淆不会 出现。
如果语法**表达式出现在函数调用表达式中 必须评估映射,其内容被视为 其他关键字参数。如果出现关键字 表达式和显式关键字参数都是TypeError 异常被提出。