2017-09-13 128 views
-4

對於一些算法,我發現它方便地定義遞歸函數,看起來是這樣的:循環遞歸函數

def f(l): 
    for i in range(2): 
     if len(l)>=1: 
      print(l+[i]) 
     else: 
      return f(l+[i]) 
f([0]) 

但行爲是我所期望的不同。它所做的是打印

[0, 0] 
[0, 1] 

但我希望它打印

[0,0] 
[0,1] 
[1,0] 
[1,1] 

不知何故,嵌套函數可以訪問變量和我,而不是開始一個新的循環與一些不同的變量,它只需繼續用這個變量i進行計數。我不明白爲什麼Python會這樣做。

我的(含糊不清)問題是爲什麼Python這樣做,是否有一些明顯的修改我的代碼,會給我最初的預期輸出?

+2

你永遠不會改變'l',它從'len(l)== 1'開始,這意味着它打印兩次並存在:你的'else'永遠不會被觸發。 – TemporalWolf

+0

輸入「[0]」如何導致你描述的輸出?請[編輯]你的問題,包括[mcve]。 – TemporalWolf

+0

@Keiwan任何有效的輸入(一個列表)可能會提供給該函數,它會輸出上述或提供的列表兩次,然後是一個0,然後是一個1。我懷疑這不是他的意圖。 – TemporalWolf

回答

1

你的代碼永遠不會遞歸。通過for

for i in range(2): 
    if len([0])>=1: 
     print([0]+[i]) 
    else: 
     return f([0]+[i]) 
# de-functified 

第一次,len([0]) >= 1True,所以它打印[0] + [0]。第二次通過for循環,len([0]) >= 1仍然是True,所以它打印[0] + [1]。然後循環結束並且控制在該函數之外傳遞。你永遠達不到你的遞歸的情況下(len(l) < 1

請注意,您預期的結果就是:

import itertools 

result = itertools.product(range(2), repeat=2) # cast to list if necessary 
0

調試

讓我們把在一個小的調試跟蹤:

def f(l): 
    print ("ENTER:", l) 
    for i in range(2): 
     print("i=", i, "len(l)=", len(l)) 
     if len(l)>=1: 
      print(l+[i]) 
     else: 
      return f(l+[i]) 

print(f([0])) 

輸出:

ENTER: [0] 
i= 0 len(l)= 1 
[0, 0] 
i= 1 len(l)= 1 
[0, 1] 
None 

分析

你叫了一個元素列表功能。因此,len(l)爲1.您在這兩個時間通過循環獲取的「true」分支。請注意,你永遠不會更改列表l。因此,你永遠不會做出你期望的遞歸調用。

REPAIR

我不能修復這個給你,因爲你沒有解釋邏輯您的期望背後L [0]將變爲1。你從來沒有分配給該元素,也不會通過全對象分配或遞歸調用的參數來重建l