循环内的Python递归调用。它是如何工作的?

循环内的Python递归调用。它是如何工作的?,python,loops,python-2.7,recursion,iteration,Python,Loops,Python 2.7,Recursion,Iteration,我遇到了一个内部带有递归函数调用的循环,循环的开始范围如下所示递增。代码输出如下顺序。然而,我无法概念化为什么会生成这个特定序列。有人能对它的工作原理提出一些见解吗。将这个递归函数转换成输出相同序列的迭代函数的可行性如何。请帮忙 代码: def foo(step=0): for i in range(step, 4): print step foo(step+1) foo() def find_anagrams(word, step=0):

我遇到了一个内部带有递归函数调用的循环,循环的开始范围如下所示递增。代码输出如下顺序。然而,我无法概念化为什么会生成这个特定序列。有人能对它的工作原理提出一些见解吗。将这个递归函数转换成输出相同序列的迭代函数的可行性如何。请帮忙

代码:

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

foo()   
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)
输出:

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

foo()   
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)
012323123123123123123123123123123123123123123123123123123123123123123123012 3 2 3 1 2 3 2 3 1 2 3 2 0 1 2 3 2 3 1 2 3 2 3 2 3

类似设计的代码以查找字谜:

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

foo()   
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)

我认为可以使用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循环。您正在迭代
范围(步骤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

这将具有与递归函数相同的输出

让我试试:

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

foo()   
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(步骤+1),都有一个称为激活记录或 框架被创建来存储关于函数调用进度的信息。 因此,当函数的执行导致嵌套函数调用时,前一个调用的执行 被挂起,其激活记录存储源代码中控制流所在的位置 应在嵌套调用返回时继续

这里是主要部分:

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

foo()   
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)
当步骤==4时,在范围(4,4)==空列表中,该时间迭代将不会发生,因此它将返回 没有一个然后它将移动到前一帧,在那里它被停止并开始一个新的迭代和递归函数调用 直到范围(4,4)

NB:Recursive base case仅在step==4、该时间范围(4,4)和返回None时使用。

每个递归都需要一个基本情况,否则它将转到无限循环。

因此,让我们看看递归跟踪:我正在添加
I
,以区分
步骤和迭代增量

# 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
在此之后,它遵循相同的递归方式,直到迭代范围被排除,即范围(4,4)


请让我知道这是否有帮助。

我将这类事情概念化的方法是在纸上手动执行程序,写下变量的值。按调用深度缩进输出将使其更容易理解。例如:没错!我试过了。也许我错过了什么。请说明。提示
打印范围(步骤4)
在for循环之前。硬编码迭代版本:是!我明白。但我的问题是循环中的递归调用如何生成这样的序列。我需要深入了解函数调用。PEP 8:在以下情况下避免多余的空格:。。。在开始函数调用的参数列表的开括号之前…@falsetru是正确的,请参阅第3项:@falsetru我认为PEP的这一部分标题为“宠物皮”很有趣。“准确地说,”鲍里斯,看来你提错人了;