以优雅的顺序应用Python函数列表

时间:2021-06-30 14:30:20

I have an input value val and a list of functions to be applied in the order:

我有一个输入值val和一个函数列表,按以下顺序应用:

funcs = [f1, f2, f3, ..., fn]

How to apply elegantly and not writing

如何优雅地运用而不写作

fn( ... (f3(f2(f1(val))) ... )

and also not using for loop:

也不用for循环:

tmp = val
for f in funcs:
    tmp = f(tmp)

Thanks Martijn for the awesome answer. There's some reading I found: https://mathieularose.com/function-composition-in-python/ .

谢谢Martijn可怕的回答。我找到了一些阅读资料:https://mathieularose.com/function-composi-- in-python/。

2 个解决方案

#1


18  

Use the reduce() function:

使用reduce()函数:

# forward-compatible import
from functools import reduce

result = reduce(lambda res, f: f(res), funcs, val)

reduce() applies the first argument, a callable, to each element taken from the second argument, plus the accumulated result so far (as (result, element)). The third argument is a starting value (the first element from funcs would be used otherwise).

reduce()将第一个参数(一个可调用的参数)应用到从第二个参数获取的每个元素,加上到目前为止的累计结果(as (result, element))。第三个参数是一个起始值(来自funcs的第一个元素将在其他情况下使用)。

In Python 3, the built-in function was moved to the functools.reduce() location; for forward compatibility that same reference is available in Python 2.6 and up.

在Python 3中,内置函数被移动到function .reduce()位置;对于前向兼容性,可以在Python 2.6和更高版本中使用相同的引用。

Other languages may call this folding.

其他语言可以称之为折叠。

If you need intermediate results for each function too, use itertools.accumulate() (only from Python 3.3 onwards for a version that takes a function argument):

如果每个函数都需要中间结果,可以使用itertools. accumul()(对于接受函数参数的版本,只能从Python 3.3开始):

from itertools import accumulate, chain
running_results = accumulate(chain(val, funcs), lambda res, f: f(res))

#2


2  

MartijnPieters answer is excellent. The only thing I would add is that this is called function composition

MartijnPieters答案是优秀的。我唯一要补充的是这叫做函数组成。

Giving names to these generics means you can use them whenever the need arises

为这些泛型命名意味着您可以在需要时使用它们

from functools import reduce

def id(x):
  return x

def comp(f,g):
  return lambda x: f(g(x))

def compose(*fs):
  return reduce(comp, fs, id)

# usage
# compose(f1, f2, f3, ..., fn) (val)

print(compose (lambda x: x + 1, lambda x: x * 3, lambda x: x - 1) (10))
# = ((10 - 1) * 3) + 1
# = 28

#1


18  

Use the reduce() function:

使用reduce()函数:

# forward-compatible import
from functools import reduce

result = reduce(lambda res, f: f(res), funcs, val)

reduce() applies the first argument, a callable, to each element taken from the second argument, plus the accumulated result so far (as (result, element)). The third argument is a starting value (the first element from funcs would be used otherwise).

reduce()将第一个参数(一个可调用的参数)应用到从第二个参数获取的每个元素,加上到目前为止的累计结果(as (result, element))。第三个参数是一个起始值(来自funcs的第一个元素将在其他情况下使用)。

In Python 3, the built-in function was moved to the functools.reduce() location; for forward compatibility that same reference is available in Python 2.6 and up.

在Python 3中,内置函数被移动到function .reduce()位置;对于前向兼容性,可以在Python 2.6和更高版本中使用相同的引用。

Other languages may call this folding.

其他语言可以称之为折叠。

If you need intermediate results for each function too, use itertools.accumulate() (only from Python 3.3 onwards for a version that takes a function argument):

如果每个函数都需要中间结果,可以使用itertools. accumul()(对于接受函数参数的版本,只能从Python 3.3开始):

from itertools import accumulate, chain
running_results = accumulate(chain(val, funcs), lambda res, f: f(res))

#2


2  

MartijnPieters answer is excellent. The only thing I would add is that this is called function composition

MartijnPieters答案是优秀的。我唯一要补充的是这叫做函数组成。

Giving names to these generics means you can use them whenever the need arises

为这些泛型命名意味着您可以在需要时使用它们

from functools import reduce

def id(x):
  return x

def comp(f,g):
  return lambda x: f(g(x))

def compose(*fs):
  return reduce(comp, fs, id)

# usage
# compose(f1, f2, f3, ..., fn) (val)

print(compose (lambda x: x + 1, lambda x: x * 3, lambda x: x - 1) (10))
# = ((10 - 1) * 3) + 1
# = 28