簡體   English   中英

循環內的Python遞歸調用。 它是如何工作的?

[英]Python recursive call inside a loop. How does it work?

我遇到了一個內部帶有遞歸函數調用的循環,其中循環的起始范圍如下所述。 該代碼輸出以下序列,如下所示。 但是,我無法概念化為什么生成此特定序列。 有人可以對其工作發表一些見識嗎? 將該遞歸函數轉換為輸出相同序列的迭代函數是多么可行。 請幫忙。

碼:

def foo(step=0):
    for i in range(step, 4):
        print step
        foo(step+1)

foo()   

輸出:

0 1 2 3 2 3 1 2 3 2 3 1 2 3 2 3 0 1 2 3 2 3 1 2 3 2 3 1 2 3 2 3 0 1 2 3 2 3 1 2 3 2 3 1 2 3 2 3 0 1 2 3 2 3 1 2 3 2 3 1 2 3 2 3

查找類似字母的相似設計的代碼:

def find_anagrams(word, step=0):
    print 'step->', step
    if step == len(word):
        print "".join(word)
    for i in range(step, len(word)):
        print step, i
        word_ = list(word)
        word_[step], word_[i] = word_[i], word_[step]
        find_anagrams(word_, step+1)

讓我嘗試:

在您的代碼段中,在每個函數調用(即foo(step + 1))中,都會創建一個稱為激活記錄或框架的結構,以存儲有關該函數調用進度的信息。 因此,當函數的執行導致嵌套函數調用時,前一個調用的執行將被掛起,並且其激活記錄將源代碼中存儲的位置存儲在源代碼中,在返回嵌套調用時,控制流應在該位置繼續。

這是主要部分:

當step == 4時,而range(4,4)==空列表,則該時間迭代不會發生,因此它將返回None。 然后它將移至上一幀,在該處停止並開始新的迭代和遞歸函數調用,直到range(4,4)。

注意:遞歸基本情況僅在step == 4時,即時間范圍(4,4)並返回None。

其他情況都需要一個基本案例,否則它將陷入無限循環。

因此,讓我們看一下遞歸跟蹤:我添加i來區分step和迭代增量。

# 1 def foo(step=0):
# 2    for i in range(step, 4):
# 3        print 'i: %d, step: %d' % (i,step)
# 4        foo(step+1)
# 5 foo()

line 5
line 1  foo with step=0  which is default
line 2  range(0,4)                       Frame: A,   0 is over, next=1
line 3  step = 0            Output: i: 0, step: 0
line 4  calling foo(0 + 1)
line 1  foo with step=1
line 2  range(1,4)                       Frame: B,   1 is over, next=2
line 3  step = 1            Output: i: 1, step: 1
line 4  calling foo(1 + 1)
line 1  foo with step=2
line 2  range(2,4)                       Frame: C,   2 is over, next=3
line 3  step = 2            Output: i: 2, step: 2
line 4  calling foo(2 + 1)
line 1  foo with step=3
line 2  range(3,4)                       Frame: D,   3 is over, next=4
line 3  step = 3,           Output: i: 3, step: 3
line 4  calling foo(3 + 1)
line 1  foo with step=4
line 2  range(4,4)                       Frame: E,
         This is an empty list, so it won't come inside the loop, so return None.
         Come back to previous Frame: D, i=3 was used, now increment to 4. So, again range(4,4)
line 2  range(4,4)          Empty list, from Frame: D, return None
         Come back to previous Frame C, now i=3, step was called with value 2
line 2  range(2,4)
line 3  step = 2            Output: i: 3, step: 2, why step == 2 because the function foo was called with step=2
line 4  calling foo(2 + 1)
line 1  foo with step=3
line 2  range(3,4)
line 3  step = 3,           Output : i: 3, step: 3
line 4  calling foo(3 + 1)
line 1  foo with step=4
line 2  range(4,4)          Empty list again, not going inside the list, return None
line 2  range(2,4)          From Frame: B, step was == 1, because the function foo was called with step=1
line 3  step: 1             Output: i: 2, step: 1,  here i ==2, because this is the second iteration of Frame B.
line 4  calling foo(1 + 1)
line 1  foo with step=2
line 2  range(2,4)
line 3  step: 2            Output: i: 2, step: 2

此后,它遵循相同的遞歸方式,直到迭代范圍被廢除,即range(4,4)

請讓我知道是否有幫助。

我認為可以通過使用stdlib來重構您的字謎代碼,從而避免遞歸循環:

from itertools import permutations

def anagrams (word):
    anagrams = set ()
    for p in permutations (word):
        anagram = ''.join (p)
        anagrams |= {anagram}
    return anagrams

def isAnagram (word1, word2):
    return sorted (word1) == sorted (word2)

考慮for循環。 您正在遍歷range(step, 4) 如果step = 0則迭代[0,1,2,3] ;如果step = 1則迭代[1,2,3] ,依此類推。 每次調用foo(step)都會在該范圍內進行迭代 - 但當前調用中要迭代的范圍不會更改 因此,對於第一個循環,您會得到一個從0到3的迭代,第二個循環是1-3,依此類推。

為什么這樣打印? 觀察。

for i in range(0,4):
    print 0
    for j in range(1,4):
        print 1
        for k in range(2,4):
            print 2
            for h in range(3,4):
                 print 3

這將具有與遞歸函數相同的輸出

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM