我有以下定义的两个函数,
def sumit(func,*args):
return func(*args)
def sumitt(*args):
return sum(args)
sumit(sumitt,2,3,4)
我通过将第二行更改为return func(args)
进行了一些实验,但我得到了一个错误。但为什么在第4行,它是sum(args)
而不是sum(*args)
?造成这种不一致的原因是什么?
答案 0 :(得分:2)
如果您查看文档sum
被定义为 -
`sum(iterable[, start])`
这意味着它正在使用一个可迭代的对象,它将遍历参数本身。
所以
def sumit(func,*args):
return func(*args)
def sumitt(*args):
print (args)
print (*args)
return sum(args)
出 -
(1, 2, 3)
1 2 3
现在你可以看到args
是一个元组,而*args
解包元素...元组是sum
接受的函数接受一个列表的元素,它正在解包。你可以做的是
def sumit(func,*args):
return func(args)
def sumitt(args):
print (args)
print (*args)
return sum(args)
现在您将整个元组发送到函数sumitt
,您可以使用*args
解压缩该函数。
1 2 3
这也是以同样的方式工作,但现在你可以看到发生了什么......
答案 1 :(得分:2)
要在每个参数上应用该函数,您需要*
解包函数的参数。
因此func(*args)
与func(arg1, arg2,...,argn)
查看解包:
>>> first, second, third = (1, 2, 3)
>>> first
1
>>> second
2
>>> third
3
但是对于sum
,函数的签名要求它需要iterable
,因此sum(arg)
将sum
(求和)直接应用于参数元组{ {1}}。
答案 2 :(得分:2)
*args
接受任意参数列表,并使其在函数范围内的args
例如
def my_print(*args):
"""print all arguments passed in"""
for arg in args:
try:
print(arg)
except:
print('argument not printable')
d = 'hello'
my_print('a', 1, 'b', d)
# outputs:
a
1
b
hello
在函数调用中将*
放在列表或元组前面解压缩列表
my_list = ['a', 1, 'b', d]
my_print(*my_list)
# produces the same output as above.
所以,你定义的第一个函数是:
def sumit(func,*args):
return func(*args)
args
args
已解压缩在此函数中,第二行不能是return func(args)
,,除非传递的函数接受列表作为第一个位置参数,并且没有其他必需参数
函数sum
接受数字的可迭代(列表或元组)并将它们相加。
你可以像这样打电话给sum
my_sum = sum([2, 3, 4])
但是sumitt
函数接受参数并在将它们传递给sum函数之前将它们转换为列表
因此,您可以致电sumitt(2, 3, 4)
,它将返回sum([2, 3, 4])
现在,sumitt
进一步包含在sumit
中,因此函数调用
sumit(sumitt,2,3,4)
调用sumitt(2, 3, 4)
,然后调用sum([2, 3, 4])
也可以通过sumit
调用sum函数,如下所示:
sumit(sum, [2, 3, 4])
第二个函数sumitt
更改sum函数的签名。这在您将动态调用许多不同函数并且您希望其签名相同的情况下非常有用。第一个函数允许您使用任意传递的参数调用任意函数。
例如,如果我定义了这样的平均函数:
def mean(*args):
return sum(args) / len(args)
然后,均值和总和有不同的签名。
在我的代码中的另一个地方,我不得不调用mean函数或sum函数,我可以这样写:
def sumitt(*args):
return sum(args)
def apply_func(func, *args):
return func(*args)
apply_func(sumitt, 2, 3, 4)
# returns 9
apply_func(mean, 2, 3, 4)
# returns 3
答案 3 :(得分:1)
如果你的函数期望单个参数,但是你有一个序列(例如一个列表),你必须指定字符*
,以便列表被扩展(解包)到序列中(否则它将是作为一个参数处理)
另一方面,因为函数sum
(内置函数python)需要序列(只有一个参数),所以在调用它之前不能展开它。
想象一下,您的args
是:
args = [1, 2, 3, 4]
使用func(*args)
,在评估func
时,它将是func(1, 2, 3, 4)
。
但sum(args)
将被评估为func([1, 2, 3, 4])