【问题标题】:How to consume/chain functions "Pythonically"?如何“以 Python 方式”使用/链接函数?
【发布时间】:2019-01-08 09:45:30
【问题描述】:

我有一组函数f(x), g(x), s(x), t(x)

它们被设计成像这样链接在一起:f(g(s(t(x))))

这些函数被设计成可以以任何顺序链接。我的代码的另一部分在列表中构建序列:[f, g, s, t]

有没有一种优雅的方式来获取列表并链接函数调用,得到最后一个结果的输出?

现在显然我可以使用一个外部类似计数器的变量来跟踪输出和一个简单的 for 循环增量索引,但我想知道是否有更 Pythonic 的方法来做到这一点?

【问题讨论】:

标签: python function functional-programming function-composition


【解决方案1】:

Reduce 是完美的答案(尽管我们需要从最里面的函数开始,因此 reversed):

import functools

functions = [f, g, s, t]
y = functools.reduce(lambda a, f: f(a), reversed(functions), x)

编辑:使用常量参数,就这么简单:

p1, p2 = 5, 42
y = functools.reduce(lambda a, f: f(a, p1, p2), reversed(functions), x)

【讨论】:

  • 很好的答案!我想知道具有多个输入的功能是否可能?像 f(x, a, b)。 a 和 b 是常数?
  • Nvm,想通了!我可以使用 lamda a,b,c,f
【解决方案2】:

Martineau 和 Amadan 已经发布了“优雅”的解决方案。现在真正的 Pythonic 解决方案是愚蠢的、简单的、无聊的:

def chain(arg, *funcs):
    # chain(42, f, g, s) => f(g(s(42)))
    result = arg
    for func in reversed(funcs):
        result = func(result)
    return result

显然不是大多数人会认为“优雅”,但它非常明显,可读,并且非常容易跟踪和调试 - 这就是最重要的 wrt/python 哲学。 p>

【讨论】:

    【解决方案3】:

    在函数式编程中,这种操作称为函数组合。 Python 在标准库中没有 compose 函数,但自己编写相当容易:

    from functools import partial
    # additional import for python 3: from itertools import reduce
    def compose(*args):
        return partial(reduce, lambda x, y: y(x), reversed(args))
    

    然后你可以像这样编写函数

    fgst_x = compose(f, g, s, t)(x)
    

    funcs = [f, g, s, t]
    fgst = compose(*funcs)
    fgst_x = fgst(x)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-09
      • 2013-05-30
      • 1970-01-01
      • 2021-05-10
      • 2020-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多