我想要接受一系列函数funclist
,并返回一个新函数,该函数接收参数列表arglist
,并应用i
在funclist
中i
的{{1}}元素中运行,将结果返回到列表中:
arglist
这不是针对def myfunc(funclist):
return lambda arglist: [ funclist[i](elt) for i, elt in enumerate(arglist) ]
中的独立函数与funclist
中的独立参数的并行/矢量化应用进行优化的。 python或numpy(或其他)中是否有内置函数会返回上面argvec
的更优化版本?它在精神上与lambda
或map
相似(但显然不一样),到目前为止我还没有找到任何东西。
答案 0 :(得分:3)
在numpy
术语中,真正的矢量化意味着在编译的代码中执行迭代的东西。通常,这需要使用适用于整个数组的numpy
函数,执行添加和索引等操作。
np.vectorize
是一种迭代多个数组的方法,并在不处理数组的函数中使用它们的元素。它在编译代码中没有多大作用,因此不会提高速度。作为将numpy
广播规则应用于您自己的标量函数的一种方式,它是最有价值的。
map
是列表推导的变体,速度基本相同。列表理解具有更强的表达能力,可以使用多个列表。
@Tore's
压缩理解是这项任务的明确表达
[f(args) for f, args in zip(funclist, arglist)]
map
可以使用多个输入列表:
In [415]: arglist=[np.arange(3),np.arange(1,4)]
In [416]: fnlist=[np.sum, np.prod]
In [417]: [f(a) for f,a in zip(fnlist, arglist)]
Out[417]: [3, 6]
In [418]: list(map(lambda f,a: f(a), fnlist, arglist))
Out[418]: [3, 6]
你的版本有点啰嗦,但功能相同。
In [423]: def myfunc(funclist):
...: return lambda arglist: [ funclist[i](elt) for i, elt in enumerate(arglist) ]
In [424]: myfunc(fnlist)
Out[424]: <function __main__.myfunc.<locals>.<lambda>>
In [425]: myfunc(fnlist)(arglist)
Out[425]: [3, 6]
它的优点是可以生成一个可以应用于不同arglists的函数:
In [426]: flist=myfunc(fnlist)
In [427]: flist(arglist)
Out[427]: [3, 6]
In [428]: flist(arglist[::-1])
Out[428]: [6, 0]
我会写myfunc
更像是:
def altfun(funclist):
def foo(arglist):
return [f(a) for f,a in zip(funclist, arglist)]
return foo
但差异只是风格上的。
=====
zip
v enumerate
的时间测试:
In [154]: funclist=[sum]*N
In [155]: arglist=[list(range(N))]*N
In [156]: sum([funclist[i](args) for i,args in enumerate(arglist)])
Out[156]: 499500000
In [157]: sum([f(args) for f,args in zip(funclist, arglist)])
Out[157]: 499500000
In [158]: timeit [funclist[i](args) for i,args in enumerate(arglist)]
10 loops, best of 3: 43.5 ms per loop
In [159]: timeit [f(args) for f,args in zip(funclist, arglist)]
10 loops, best of 3: 43.1 ms per loop
基本相同。但map
快2倍
In [161]: timeit list(map(lambda f,a: f(a), funclist, arglist))
10 loops, best of 3: 23.1 ms per loop
将迭代打包在可调用中也更快
In [165]: timeit altfun(funclist)(arglist)
10 loops, best of 3: 23 ms per loop
In [179]: timeit myfunc(funclist)(arglist)
10 loops, best of 3: 22.6 ms per loop