2012-09-14 30 views
2

可能重複:
function making功能使得

>>> g=lambda x:x+1 
>>> composition=lambda f,g:(lambda x:f(g(x))) 
>>> f=g 
>>> f=composition(f,g) 
>>> f(9) 
11 
>>> f=composition(f,g) 
>>> f=composition(f,g) 
>>> f=composition(f,g) 
>>> f(9) 
14 

代替使用函數組合物(F,G)的,我做了以下

>>> f=g 
>>> f=lambda x:f(g(x)) 
>>> f(8) 
RuntimeError: maximum recursion depth exceeded 

我剛旨在替代相應的函數組合丁lambda表達。我很困惑爲什麼f = composition(f,g)不會產生遞歸,但是f = lambda x:f(g(x))。

回答

2

對於第一種:

當你調用composition(f, g),要創建圍繞這些變量的內容封閉。正在返回的lambda正在尋找變量名稱fg在其本地範圍內 - 它們都將引用在第一行創建的g lambda。

對於第二個:

在第二個,當f被調用時,它會在其「本地」範圍,這實際上是在全球範圍內f - 並發現本身,從而創造無限遞歸。

這裏的關鍵在於f的查找發生在執行,而不是當lambda被定義時。

1

當你這樣寫:

f=lambda x:f(g(x)) 

產生的拉姆達的意思是「叫什麼f是在範圍上調用任何g是在X範圍的結果」。

當你這樣寫:

f=composition(f, g) 

產生的功能是指「任何調用來組成的第一個參數是在調用任何的組合物的第二個參數是在結果」。

我不確定哪部分細節需要更好地理解,以便弄清楚,但我會猜測。在Python中傳遞的參數始終是通過引用,而不是通過名稱。所以,當你調用composition(f,g)時,你傳遞的是f指向的函數對象,而不是「變量」f。但是當你定義一個lambda時,這隻發生在範圍內,所以你引用了f本身。

作爲一個側面說明,這是Guido不喜歡使用lambda語法的人的一部分原因。如果你重寫這樣的代碼,情況會更加明顯:

def g(x): return x+1 
def composition(f,g): 
    def composed(x): return f(g(x)) 
    return composed 
f=g 
f=composition(f,g)