2013-03-14 103 views
7

我剛開始學習python。我遇到了lambda函數。在其中一個問題上,作者要求編寫一個數字階乘的單線性lambda函數。Python lambda函數來計算一個數的階乘

這是一個被賦予瞭解決方案:

num = 5 
print (lambda b: (lambda a, b: a(a, b))(lambda a, b: b*a(a, b-1) if b > 0 else 1,b))(num) 

我無法理解的怪異的語法。 (a,b)是什麼意思?

有人可以解釋一下嗎?

謝謝

+9

我得到一個更好的:'拉姆達b:math.factorial(b)' – JBernardo 2013-03-14 04:50:05

+2

不要重新發明方形的車輪。 – ShuklaSannidhya 2013-03-14 04:53:28

回答

5

的產品正是這種簡單:

n=input() 

print reduce(lambda x,y:x*y,range(1,n+1)) 
6

因子本身幾乎和你所期望的一樣。你推斷a是......階乘函數。 b是實際參數。

<factorial> = lambda a, b: b*a(a, b-1) if b > 0 else 1 

該位是階乘的應用:

<factorial-application> = (lambda a, b: a(a, b))(<factorial>, b) 

a是階乘函數本身。它將自己作爲第一個參數,評估點作爲第二個參數。這隻要能推廣到recursive_lambda因爲你不介意的a(a, b - 1)代替a(b - 1)

recursive_lambda = (lambda func: lambda *args: func(func, *args)) 
print(recursive_lambda(lambda self, x: x * self(self, x - 1) if x > 0 else 1)(6)) 
# Or, using the function verbatim: 
print(recursive_lambda(lambda a, b: b*a(a, b-1) if b > 0 else 1)(6)) 

所以我們有外部分:

(lambda b: <factorial-application>)(num) 

正如你所看到的所有調用必須通過爲評估點。


如果實際上想有一個遞歸拉姆達,你可以只name the lambda

fact = lambda x: 1 if x == 0 else x * fact(x-1) 

如果沒有,你可以使用a simple helper function。您會注意到ret是一個可以引用自身的lambda表達式,與之前沒有lambda可以引用自身的代碼不同。

def recursive_lambda(func): 
    def ret(*args): 
     return func(ret, *args) 
    return ret 

print(recursive_lambda(lambda factorial, x: x * factorial(x - 1) if x > 1 else 1)(6)) # 720 

這兩種方式,你不必訴諸通過lambda本身的荒謬手段。

+0

澄清:'a'被傳遞給自己?準確地說, – ApproachingDarknessFish 2013-03-14 04:50:51

+0

@ValekHalfHeart。 – 2013-03-14 04:52:28

+1

這是一個全新的扭曲水平。 – ApproachingDarknessFish 2013-03-14 04:53:43

6

讓我們剝開這個像洋蔥一樣開放的內膽。

print (lambda b: (Y))(num) 

我們正在一個匿名函數(關鍵字拉姆達意味着我們對輸入的一系列參數的名字,然後的一個冒號,然後使用這些參數的函數),然後將它傳遞給NUM滿足其一個參數。

(lambda a, b: a(a, b))(X,b) 

在lambda裏面,我們定義了另一個lambda。調用這個lambda Y.這個需要兩個參數a和b。一個被調用,a和b,所以是發生本身和一個其他參數

  (lambda a, b: b*a(a, b-1) if b > 0 else 1 
      , 
      b) 

這些是Y的第一個中的參數可調用被lambda函數,調用它X.我們可以看到X是階乘函數,第二個參數將成爲它的數字。

也就是說,如果我們上去看看Y,我們可以看到,我們稱之爲:

X(X, b) 

這將做

b*X(X, b-1) if b > 0 else 1 

,並調用自身,形成的遞歸部分階乘。

回頭看,我們可以看到b是我們傳入最外層lambda的num。

num*X(X, b-1) if num > 0 else 1 

,因爲它被寫了一個令人困惑的一個襯墊:)

+0

這是一場線上線上比賽。我正在爲此做準備。這是令人困惑的,但花了很多時間之後,我想我已經把它放下了。謝謝 – suparngp 2013-06-24 23:20:59

2

有關於這個功能的兩個硬盤部分這是一種混亂。
1. lambda a, b: b*a(a, b-1) if b > 0 else 1
2. 「B」 這是如下因素1.

爲1,這不外乎:

def f(a, b): 
    if b > 0: 
     b * a(a, b - 1) 
    else: 
     1 

對於2,本B

(lambda b: (lambda a, b: a(a, b))(lambda a, b: b*a(a, b-1) if b > 0 else 1,b))(num) 
                     (this one) 

實際上是這個B:

(lambda b: (lambda a, b: a(a, b))(lambda a, b: b*a(a, b-1) if b > 0 else 1,b))(num) 
    (this one) 

原因是它不在第二個和第三個lambda的定義裏面,所以它指的是第一個b。

後,我們應用Num和剝離外部函數:

(lambda a, b: a(a, b)) (lambda a, b: b*a(a, b-1) if b > 0 else 1, num) 

它只是將函數應用於一個元組,(拉姆達一個,B:B * A(A,B-1)如果B> 0,否則,1,NUM)
讓我們把這個作爲元組(F,NUM)(F的高清高於) 應用上lambda a, b: a(a, b),我們得到

F(男,NUM)。

假設你num是5
用F的definiton,它首先計算爲

5 * f(f, 4) 

然後到:

5 * (4 * f(f, 3)) 

所有到

5 * (4 * (3 * (2 * (1 * f(f, 0))))) 

方式f(f,0)變爲1.

5 * (4 * (3 * (2 * (1 * 1)))) 

這裏我們去,因子5。

+0

謝謝@octref。你給出了一個清晰的解釋。 – suparngp 2013-06-24 23:21:46

1

我們可以使用下面的lambda表達式

 fact = lambda n:1 if n==0 else n*fact(n-1) 
    print(fact(5) 
    >>> 120 
0

廣義高清遞歸拉姆達的是如下

recursive_lambda = (lambda func: lambda *args: func(func, *args)) 
0

非常漂亮解釋!只有一個較小的修正:如果B> 1 NOT如果B> 0

結果是相同的,但在邏輯上,因爲它是執行一個不必要的附加環(乘以1即使)

維基百科=> n多正確!,是所有正整數小於或等於n