2009-08-17 75 views
1

我碰到了一個小的遞歸代碼。我已經打印輸出,它的打印效果很好,但是當我嘗試將計數器實際計入我的答案時,它會給我提取錯誤。python scooping和遞歸

total = 0 
def foo(me, t): 
    if t<0: 
     return 
    if t==0: 
     total = total+1 
     return 
    for i in range(1, me+1): 
     total = total+1 
     return foo(i, t-i) 

它說,分配前引用了局部變量,那麼,我想是指在第一線總....它不是全局變量,我曾嘗試使用全局很好,但徒勞無功。

這是純粹的舀問題,任何想法?

+1

這個問題你的意思是範圍界定? – Svante 2009-08-17 07:50:16

+2

順便說一句,你的「for」循環只會在每個遞歸中執行一次,而'i'將始終爲1. – Svante 2009-08-17 07:54:43

回答

1

您忘記確保在您的功能中將總數設置爲全局。你說過:「我試圖用全球化,但徒勞無益。」但是當我嘗試它下面不拋出任何錯誤:正如其他人所提到

total = 0 
def foo(me, t): 
    global total 
    if t<0: 
     return 
    if t==0: 
     total = total+1 
     return 
    for i in range(1, me+1): 
     total = total+1 
     return foo(i, t-i) 
+0

它不會拋出錯誤,但回答將不正確。例如如果你嘗試foo(99,100),你會得到101,這是不正確的。但如果您發出完整的申報和使用情況並開始打印,則會打印正確的次數。 – hasanatkazmi 2009-08-17 08:02:16

+0

這個線程可能會詳細說明我想說的: http://mail.python.org/pipermail/python-list/2001-September/104562.html – hasanatkazmi 2009-08-17 08:06:05

+2

你的分析是不正確的:101是正確的答案。每次擊中第7行或第10行時,您總共添加一個;後者是你在[1,100]中擊中t,而在t = 0時是前者。 「全球化」不是問題。 – 2009-08-17 08:29:44

2

,你需要完全的global聲明。另外,正如Svante所指出的那樣,由於i總是1,所以for循環是不必要的。所以,你的代碼的等效版本:

total = 0 
def foo(me, t): 
    global total 
    if t < 0: 
     return 
    total = total + 1 
    if t == 0: 
     return 
    return foo(1, t-1) 

foo(99, 100) 
print total 

它應該是更容易地看到,FOO(99,100)的確會因爲101你基本上倒計時從100到0。我不當然,爲什麼你認爲不然?

1

我不知道你真的知道你正在嘗試做的... (至少如果你說​​,加上全球關鍵字給出了不正確的結果,但沉默的錯誤)

需要聲明的「全球總」如果你要嘗試引用總(你正在做的)

(什麼是你當你執行FOO(99,100)預期?)

也許你的邊界條件錯了?

「事業的參數(99,100)

  1. foo將跳過兩個if語句
  2. 環下面的循環:

    for i in range(1, 100): 
    total += 1 
    return foo(i, 100-i) 

這實際上相當於


    else: 
    total += 1 
    return foo(1, 99) 

(像斯萬說的話)的基礎上

你的兩個if條件 富(1,99)將正確生成總+ = 100

(99次將執行你的「其他」聲明使共有100個,最後將達到牛逼== 0和執行最後的決賽中,如果它會推動總到你的「不正確」 101)

,你也應該使用ELIF你的第二個案例

1

作爲一般性的adv冰,遞歸應該總是使用返回值,而不是全局變量。遞歸已經有了它自己的複雜負擔,增加了副作用,而不清晰的接口會使它變得更糟。

你應該嘗試在此線的東西:

def foo(me, t): 
    if t<0: 
     return 0 
    if t==0: 
     return foo(me, t+1) 
    return foo(me-1, t) 
    for i in range(1, me+1): 
     tot = foo(i, t-i) 
    return tot 

注意:此代碼是,它將解決您的問題,它會自身甚至工作;我只是想給出一種關於如何設計易於管理的遞歸的想法。

0

感謝人們,謝謝youarf,Liffredo。 我錯了,我沒有注意到我在加入東西之前回來了,循環只運行了一次,我修復了代碼。它是這樣的:

def foo(me, t): 
    if t<0: 
     return 0 
    if t==0: 
     return 1 
    toreturn = 0 
    for i in range(1, me+1): 
     toreturn = toreturn + foo(i, t-i) 
    return toreturn 

這個片段是在http://projecteuler.net/index.php?section=problems&id=76