递归错误组合lambda函数

3

我正在尝试编写一个函数,用于组合任意数量的lambda函数。

我有两个简单的lambda函数。

f = lambda x: x + 1
g = lambda x: x**2

我尝试写的一个组合函数如下:

def compose(*functions):
    composed = lambda x: x  # Function that returns input
    for function in reversed(functions):
        composed = lambda x: function(composed(x))
    return composed

我的想法是循环遍历可变数量的函数,每次将新的函数包含在composed函数中。
然后我可以创建一个由fg组成的函数。
c = compose(f, g)

那么调用 c(5) 应该返回 f(g(5)),即 26。但是实际上,我得到了...
RecursionError: maximum recursion depth exceeded

我认为引入一个中间变量可能会解决这个问题。

def compose(*functions):
    composed = lambda x: x  # Function that returns input
    for function in reversed(functions):
        intermediate = lambda x: function(composed(x))
        composed = intermediate
    return composed

但是仍然报错。

有没有办法解决这个问题?

1个回答

2
首先,我认为您的方法将遭受“迟绑定闭包”的影响,因为lambda中的function仅会在迭代结束时取到函数的最后一个值。其次,由于第一个原因,“composed”仅会在最后一个调用自身,因为lambda会调用“composed”的最后一个值——它本身!
一种可能的解决方案是在每次迭代中将“composed”和“function”绑定到“lambda”上:
def compose(*functions):
    composed = lambda x: x
    for function in reversed(functions):
        composed = lambda x, function=function, composed=composed: function(composed(x))
    return composed

print(compose(f, g)(5))
# 26

但是你的整体问题看起来像是 functools.reduce 的一个好应用案例:

from functools import reduce

def compose(*functions):
    def inner(v):
        return reduce(lambda x, y: y(x),  reversed(functions), v)
    return inner

print(compose(f, g)(5))
# 26

1
好的解决方案,但你能发现 OP 尝试中的 bug 吗? - juanpa.arrivillaga
@juanpa.arrivillaga 看一下它 - Moses Koledoye
是的,我刚才弄明白了,这是由于晚绑定导致的。 - juanpa.arrivillaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接