首页 > 解决方案 > 为什么遇到'return'语句时执行不停止?

问题描述

当我阅读这段代码时:

def factorial(number):
    if not isinstance(number, int):
        raise TypeError("Sorry. 'number' must be an integer.")
    if number < 0:
        raise ValueError("Sorry. 'number' must be zero or positive.")
    
    def inner_factorial(number):
        if number <= 1:
            return 1
        return number * inner_factorial(number - 1)
    return inner_factorial(number)

我无法理解这部分代码:

    def inner_factorial(number):
        if number <= 1:
            return 1
        return number * inner_factorial(number - 1)
    return inner_factorial(number)

我的意思是,当 Python 看到语句时,它不会停止代码return吗?我想知道return number * inner_factorial(number - 1)代码行是如何工作的。

标签: pythonreturn

解决方案


您突出显示的行属于内部功能。如果有帮助,您可以将它们分开考虑,如下所示。

def inner_factorial(number):
    if number <= 1:
        return 1
    return number * inner_factorial(number - 1)  # 1

def factorial(number):
    if not isinstance(number, int):
        raise TypeError("Sorry. 'number' must be an integer.")
    if number < 0:
        raise ValueError("Sorry. 'number' must be zero or positive.")
    
    return inner_factorial(number)  # 2

factorial函数仅返回inner_factorial传入的相同值(第 2 行)。然后,inner_factorial被调用并返回自身,这意味着它是一个递归调用inner_factorial将调用自己,直到number变得小于或等于1


递归是如何工作的?

当我们运行时factorial(4),这些值被推送到调用堆栈(调用堆栈是堆栈数据结构,用于存储有关计算机程序的活动子例程的信息。调用堆栈很重要,因为每个任务都可以拥有自己的单独堆栈。这意味着每个被调用的函数可以同时为不同的任务执行不同的事情。另一个优点是调用堆栈自动支持递归调用。)在程序中,将有一个新inner_factorial函数压入调用堆栈直到inner_factorial返回1。要看到这一点,可以在函数的返回语句中使用带有断点的调试器(我使用 PyCharm 的)inner_factorial并使用单执行按钮。因此,factorial(4)我们填充了 4 个新的inner_factorials

在此处输入图像描述

如果我继续单击 step into 按钮,这些inner_factorials将被一一删除。(从调用堆栈中弹出,这就是为什么它以与被推入调用堆栈时相反的顺序发生)

另一件事是这种乘法是一次完成还是顺序完成。*为了测试这一点,我创建了一个函数multiply来揭示幕后发生的事情,而不是使用乘法。看来乘法是按如下方式完成的: 2x1 → 3x2 → 4x6. 可以通过运行以下脚本来说明此行为:

import time


def inner_factorial(number):
    if number <= 1:
        return 1
    time.sleep(1)


    def multiply(a, b):
        print(f"multiplying {a} with {b}.")
        time.sleep(1)
        return a * b
    return multiply(number, inner_factorial(number - 1))  # <- change is in here.
# where multiply (number being popped of the call stack, return a*b)

# multiplying 2 with 1.
# multiplying 3 with 2.
# multiplying 4 with 6.
# 24

inner_factorial(4)

如果我误解任何部分并解释错误,请告诉我。


推荐阅读