2016-11-10 50 views
3

我想寫一個構成任何數量的lambda函數的函數。構成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功能包括裏面的一個新功能。

然後,我可以做一個功能是f的組成和g

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 

但是提出了同樣的錯誤。

有沒有辦法解決這個問題?

回答

2

首先,我認爲你的方法將會受到延遲關閉綁定的影響,因爲function在lambda中只會在迭代結束時取最後一個函數值。其次,由於第一個原因,composed最終只會遞歸調用自己; composed - lambda - 調用最後一個值composed - 本身!

一個可能的解決辦法是在每次迭代綁定composedfunctionlambda

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的錯誤嗎? –

+0

@ juanpa.arrivillaga看看它 –

+0

是的,只是想出了它是由於遲綁定。 –