【发布时间】:2016-04-09 09:17:57
【问题描述】:
在 Python 中是否有一个函数可以做到这一点:
val = f3(f2(f1(arg)))
通过输入(例如):
val = chainCalling(arg,f3,f2,f1)
我只是想,因为 python(可以说)是一种函数式语言,所以我正在寻找的函数会使语法更明亮
【问题讨论】:
标签: python
在 Python 中是否有一个函数可以做到这一点:
val = f3(f2(f1(arg)))
通过输入(例如):
val = chainCalling(arg,f3,f2,f1)
我只是想,因为 python(可以说)是一种函数式语言,所以我正在寻找的函数会使语法更明亮
【问题讨论】:
标签: python
使用reduce() function 链接调用:
from functools import reduce
val = reduce(lambda r, f: f(r), (f1, f2, f3), arg)
我用的是forward-compatible functools.reduce() function;在 Python 3 中,reduce() 不再位于内置命名空间中。
这当然也可以做成单独的函数:
from functools import reduce
def chain(*funcs):
def chained_call(arg):
return reduce(lambda r, f: f(r), funcs, arg)
return chained_call
【讨论】:
您可以使用 reduce() functool — 正如 Martijn briantly 建议的那样,或者您可以自己编写非常简单:
def chainCalling(arg, *funcs):
if len(funcs) > 0:
return chainCalling(funcs[0](arg), funcs[1:])
return arg
或者,作为不使用递归的替代方案——因此不受 Martijn 建议的调用堆栈限制:
def chainCalling(arg, *funcs):
result = arg
for f in funcs:
result = f(result)
return result
显然,您会希望这样称呼它,以避免参数的无用颠倒:
chainCalling(arg, f1, f2, f3)
【讨论】:
reduce() 文档为您提供了一个起点。
funcs[-1] 和funcs[:-1]。我的版本需要在循环中使用reversed(funcs)。
reduce 的注释:(sic) "如果您确实需要它,请使用 functools.reduce();但是,99% 的时间显式 for 循环更具可读性。 ”。虽然我不得不承认,当我认为它有意义时,我仍然是 reduce 函数的用户。
可能有点晚了,但请在下面尝试我的解决方案。 chain_func 本质上是创建一个新的包装函数,在运行时调用时调用链中的所有底层函数。
def chain_func(*funcs):
def _chain(*args, **kwargs):
cur_args, cur_kwargs = args, kwargs
ret = None
for f in reversed(funcs):
cur_args, cur_kwargs = (f(*cur_args, **cur_kwargs), ), {}
ret = cur_args[0]
return ret
return _chain
【讨论】:
如果您想将函数链应用于多个参数,您可以创建一个聚合函数。
g = lambda x: f3(f2(f1(x)))
或更灵活(当有任意功能列表时):
from functools import reduce, partial
f3 = lambda x: -x
f2 = lambda x: x ** 2
f1 = lambda x: x + 1
function_list = (f1, f2, f3)
g = partial(reduce, lambda r, f: f(r), function_list)
print(g(3)) # results in -16
【讨论】: