【问题标题】:Is there a chain calling method in Python?Python中有链式调用方法吗?
【发布时间】:2016-04-09 09:17:57
【问题描述】:

在 Python 中是否有一个函数可以做到这一点:

val = f3(f2(f1(arg)))

通过输入(例如):

val = chainCalling(arg,f3,f2,f1)

我只是想,因为 python(可以说)是一种函数式语言,所以我正在寻找的函数会使语法更明亮

【问题讨论】:

    标签: python


    【解决方案1】:

    使用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
    

    【讨论】:

    • 你应该链接到docs.python.org/3.5/library/…而不是v2版本
    • @zmo:大部分人还在使用 Python 2;如果问题中没有特定的版本指示符,我会链接到 Python 2 文档,并在适用的情况下解释版本之间的任何差异。
    • 好吧,您在代码中使用了 python3 版本,因此要么链接到 v3,要么链接到两者(因为你提供了两个链接);-)
    • @zmo:我给了一个向前兼容的版本,它存在于 Python 2 中。
    【解决方案2】:

    您可以使用 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)
    

    【讨论】:

    • 有了足够的函数,这将达到递归限制。为什么将自己限制在 1000 个电话,上衣?这是一个循环,只需使用一个循环。 reduce() 文档为您提供了一个起点。
    • 只是建议一种替代解决方案,它易于编写和理解,并且非常适合小功能列表。虽然你完全正确,它有它的局限性
    • 你是对的,错过了他想要返回结果,更正代码
    • 另外,他们的示例调用反转了函数,因此您需要使用funcs[-1]funcs[:-1]。我的版本需要在循环中使用reversed(funcs)
    • 作为对reduce 的注释:(sic) "如果您确实需要它,请使用 functools.reduce();但是,99% 的时间显式 for 循环更具可读性。 ”。虽然我不得不承认,当我认为它有意义时,我仍然是 reduce 函数的用户。
    【解决方案3】:

    可能有点晚了,但请在下面尝试我的解决方案。 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
    

    【讨论】:

    • 你的函数可能是一个很好的解决方案,但它不是 python by def
    • @ShaiBen-Dor 你说的“不是 python by def”是什么意思?上面的代码适用于 python 3。
    • 我的意思是你发明轮子,看正确答案,它使用python标准函数来达到目的。感谢您的回复。
    【解决方案4】:

    如果您想将函数链应用于多个参数,您可以创建一个聚合函数。

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多