为什么我用这个递归函数得到这个输出?

时间:2016-12-08 20:40:02

标签: python

def test(n):
    if n == 0:
        return
    print("This should print n times")
    test(n - 1)

    print("This should not print")


test(2)

输出:

This should print n times
This should print n times
This should not print
This should not print

当函数调用自身(recurses)时,为什么This should not print被打印出来?它不应该重新开始回到顶部吗?

3 个答案:

答案 0 :(得分:0)

是的,你是部分正确的。当一个函数被调用时,它从上到下运行或被告知停止(例如返回)。函数运行后,程序从它调用函数的行继续。 E.g。

>>> def myFunc():
    print("This function is running")


>>> def OtherFunc():
    myFunc()
    print("The other function has finished running")

>>> OtherFunc()
This function is running
The other function has finished running

您期望发生的是函数调用充当return关键字,以立即结束函数。你的程序是这样的,但是(带有实际数字的n子):

def test(2):
    if 2 == 0:
        return
    print("This should print n times")
    test(2 - 1) #The program is told to run the function again

def test(1):
        if 1 == 0:
            return
        print("This should print n times")
        test(1 - 1) #The program is told to run the function again

def test(0):
            if 0 == 0:
                return #This exits the function, and returns to the function that called it, test(1)

print("This should not print") #This is the only line left in test(1), so it runs, and the returns to test(2), which called test(1)

print("This should not print") #This is the only line left in test(2), so it is run. The program ends as there are no more lines of code after when you called test(2)

因此调用该函数并不会结束当前运行的函数,该函数将在它调用的函数完成后运行。

此代码将执行您想要的操作:

def test(n):
    if n == 0:
        return
    print("This should print n times")
    test(n - 1)

    return #This will exit the function

    print("This should not print")


test(2)

我希望这有帮助!

答案 1 :(得分:0)

一旦测试(n-1)到达其内部返回,将执行不需要的打印。返回仅退出当前函数调用,继续调用它的下一行。它并没有清除整个堆栈。

答案 2 :(得分:0)

Welllll主要是。当你说“重新开始”时,你被绊倒的部分。该函数没有重新开始 - 它正在调用本身。在纯函数中更容易看到 - 再看看。

def add(x, y):
    if y == 0:
        return x
    return 1 + add(x, y-1)

这将基本上通过计算它们将两个数字加在一起(这是一个可怕的想法,但出于说明目的......)让我们通过一些调用来跟踪它。

>>> add(100, 4) = 1 + add(100, 3)
    # because we're returning 1 + add(x, y-1)
... add(100, 3) = 1 + add(100, 2)
... add(100, 2) = 1 + add(100, 1)
... add(100, 1) = 1 + add(100, 0)
... add(100, 0) = 100  # this is called the base case.

然而,答案不是100,因为如果你的功能刚刚重新开始就是如此。每个对add的调用都会解析为它们返回到函数原始运行的值,所以你得到了:

>>> add(100, 4) = 1 + (1 + add(100, 2))  # subbing out...add(100, 3)
                = 1 + (1 + (1 + add(100, 1)))  # ... add(100, 2)
                = 1 + (1 + (1 + (1 + add(100, 0))))  # ... add(100, 1)
                = 1 + (1 + (1 + (1 + 100)))  # ... add(100, 0)
                = 1 + 1 + 1 + 1 + 100  # because addition is associative
                = 104

通过这些示例,我们可以看到它如何适用于您的功能。条件中的return完美无缺,但只能从最里面的函数中踢出。

# where a = "This should print n times"
#   and b = "This should not print"
>>> test(2) = print(a); test(1); print(b)
... test(1) = print(a); test(0); print(b)
... test(0) = None  # because of the early-exit

把所有这些东西都放进去,你有:

>>> test(2) = print(a); (print(a); None; print(b)); print(b)
#            test(1) ---^
#            test(0)---------------^

其中包含2 print(a)和2 print(b) s。