2013-12-23 40 views
1

我需要創建一個遞歸函數repeat,它接受一個函數,並使用該函數的n次值與x的值。這裏有一個迭代版本,詳細解釋了我的問題。使用lambda表達式的遞歸函數

def repeat(fn, n, x): 
    res = x 
    for i in range(n): 
     res = fn(res) 
     print(res) 
    return res 

print(repeat(lambda x: x**2, 3, 3)) returns 6561 

首先需要3^2,然後是3^2^2是81話又說回來3^2^2^2 = 6561. 我怎樣才能使這個遞歸,因此它可以像這樣工作。

square_three_times = repeat(lambda x: x**2, 3) 
print(square_three_times(3)) return 6561 

我試過類似的東西,但我真的失去了,不知道該怎麼做。

def repeat(fn, n): 
    if n == 1: 
     return fn(n): 
    else: 
     def result(x): 
      return fn(n) 
    return repeat(fn,result(x)) 

這顯然不會工作,因爲遞歸會一直持續下去。但我不知道我該怎麼寫這個代碼,因爲我需要在進行下一步9^2之前先計算3^2等等。

+0

您是否需要使其遞歸,還是需要它像這樣工作?遞歸不一定涉及。 – Ryan

+0

我需要它是遞歸的yes – Pierre

+0

爲什麼你不使用遞歸變體的'x'參數? – filmor

回答

4

首先,你已經得到了基本情況不對:

if n == 1: 
    return fn 

畢竟,repeat(fn, 1)僅僅是一次適用fnfn功能。

現在,如果基本情況是當n == 1,遞歸情況幾乎總是會通過n - 1給你自己。

那麼,repeat(fn, n)repeat(fn, n-1)有什麼區別?如果你不能弄清楚,展開一個簡單的情況下,出在你的頭上或在紙上:

repeat(fn, 3)(x): fn(fn(fn(x))) 
repeat(fn, 2)(x): fn(fn(x)) 

而現在很明顯:repeat(fn, n)是一回事fn(repeat(fn, n-1)),對不對?所以:

else: 
    def new_fn(x): 
     return fn(repeat(fn, n-1)(x)) 
    return new_fn 

然而,隨着filmor在評論中指出,這將是更容易在這裏使用partial

def repeat3(fn, n, x): 
    if n == 1: 
     return fn(x) 
    else: 
     return fn(repeat3(fn, n-1, x)) 

def repeat(fn, n): 
    return functools.partial(repeat3, fn, n) 
+0

由於我嘗試使用你的第一個例子,但我得到無效語法返回FN,我編輯了我的原始帖子。編輯:沒關係,發現我愚蠢的misstake。 – Pierre

-1

您可以在舊的重複方面非常簡單地定義這個功能:

repeat_new = lambda fn, n: lambda x: repeat(fn, n, x) 

square_three_times = repeat_new (lambda x: x**2, 3) 
print(square_three_times(3)) 
+0

是的,但這不是遞歸的,他的問題的整個重點是如何遞歸地做到這一點。 (另外,這只是編寫'partial'的一種更詳細的方式。) – abarnert

+0

@abarnert:'functool.partial'只給你一個偏好等級,不是嗎?使用'partial'將'f(x,y,z)'變成'g(x)(y)(z)',而不是使用'g = lambda x:lambda y:lambda z: f(x,y,z)' – Eric

+0

這就好像在說'lambda'只能讓你明確地寫出一個偏好等級......你總是可以在partial中調用partial。 – abarnert