寻找解释这个递归Python片段中发生了什么?

huangapple go评论70阅读模式
英文:

Looking for explanation of what's happening in this recursive Python snippet?

问题

以下是翻译好的代码部分:

def fun(a):
    if a > 30:
        return 3
    else:
        return a + fun(a+3)
print(fun(25)) # 输出 56

以下是翻译好的第二段代码:

def fun(a):
    if a > 30:
        return 3
    else:
        return fun(a+3)
print(fun(25)) # 输出 3

希望这些翻译对您有帮助。如果您有其他问题,请随时提出。

英文:

The snippet:

def fun(a):
        if a > 30:
            return 3
        else:
            return a + fun(a+3)
print(fun(25)) # prints 56

Now my question is this: The return from the function does not seem assigned specifically to a. So how does the program ever reach the a > 30 branch, and terminate?

In practice, the snippet prints 56. How does the function arrive at this value? One answer seems to be: the return value of fun(a+3) is indeed assigned to a, resulting in a becoming 53 i.e. (25 + (25 + 3)) on the first pass and 56 i.e. (53 + 3) on the next pass.

I tried:

def fun(a):
        if a > 30:
            return 3
        else:
            return fun(a+3)
print(fun(25)) 

And got 3. So a + fun(a + 3) should return 28 to the print command.

答案1

得分: 0

因为对函数fun()的递归调用,当您将初始输入设为25时,它会以输入28再以输入31的方式调用相同的函数,此时退出函数,因为输入大于30。但由于Python调用堆栈卸载的顺序,返回的值不是3。

您可以使用“pythontutor”网站来可视化Python调用执行中的调用堆栈的使用情况。只需复制粘贴您的代码到Python Tutor,然后点击“Visualize Execution”按钮。通过逐一迭代语句,使用“Next”按钮,它将显示您如何最终得到函数返回值为56的详细路径。

英文:

Because of the recursive call to the function fun(), when you pass it the initial input=25, it calls the same function with input=28 and then with input=31 at which point it exits the function since input > 30. But the retuned value is not 3 due to the order the python call stack is unloaded.

You can use the "pythontutor" website to visualize how the call stack is used in python call execution. Just copy paste your code at Python Tutor and click the "Visualize Execution" button. As you iterate through the statements one by one using "Next", it will show you the detailed path to how the function ends up returning 56.

答案2

得分: 0

以下是翻译好的部分:

解释和可视化发生的事情的一种方法是使用“打印调试”。
添加额外的print()调用(以及lvl用于跟踪每个递归级别)后,代码如下:

def fun(a, lvl=0):
    print("  " * lvl, f"fun({a}, {lvl})", end="")
    if a > 30:
        print(" => 3")
        return 3
    else:
        print(f" => {a} + fun({a + 3}, {lvl + 1})")
        return a + fun(a + 3, lvl + 1)

print(fun(25)) # 打印 56

您将看到以下输出将其全部解释:

❯ python foo.py
 fun(25, 0) => 25 + fun(28, 1)
   fun(28, 1) => 28 + fun(31, 2)
     fun(31, 2) => 3
56 

因为25 + 28 + 3 = 56

每行代表同一函数的一次调用,每个调用都有自己独立的作用域。变量a在这些调用/作用域之间既不被分配也不共享。

英文:

One way to explain and visualize what's happening is with print debugging.

With the additional print() calls added (and lvl to track each level of recursion):

def fun(a, lvl=0):
    print("  " * lvl, f"fun({a}, {lvl})", end="")
    if a > 30:
        print(" => 3")
        return 3
    else:
        print(f" => {a} + fun({a + 3}, {lvl + 1})")
        return a + fun(a + 3, lvl + 1)

print(fun(25)) # prints 56

You'll see the following output breaking it all down:

❯ python foo.py
 fun(25, 0) => 25 + fun(28, 1)
   fun(28, 1) => 28 + fun(31, 2)
     fun(31, 2) => 3
56 

Because 25 + 28 + 3 = 56

Each line represents one call of the same function, each with its own independent scope. The variable a never gets assigned to nor shared between these calls/scopes.

huangapple
  • 本文由 发表于 2023年5月17日 12:05:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76268488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定