在递归中在哪里使用 return

where to use return in recursion

在 C 中这段代码有效,这里我在递归调用函数时没有使用 return。它给出正确的输出

int gcd(int a, int b)
{
    if(b == 0)
        return a;
    gcd(b, a % b);
}

但是,如果我在 python 中编写相同的代码,此代码 returns None(我认为值应该 return 从 return if 条件内的语句)

def gcd(a, b):
    if b == 0:
        return a
    gcd(b, a % b)

要使此代码有效,我必须添加 return

def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

但是为什么呢? C 和 Python 代码执行之间的本质区别是什么?如果我在递归调用时添加额外的 return,C 中的代码也可以工作,为什么它不抛出错误?

为什么?错误的假设。顺便说一句,这不是关于 Python 的问题,而是关于 C.

的问题

您的 C 代码无效。它具有 undefined behaviour,因为您 使用 函数调用的 returned 值,其中控制路径实际上没有使用 return 语句 return一个。如果您使用正确的 options/settings 进行编译,您的编译器可能会对此发出警告。 IE。这不是编译 C 程序的方式:

% gcc -c 123.c

相反,您启用所有警告,将它们变成错误。例如在 GCC -Wall-Wextra-Werror-pedantic

% gcc -c 123.c -Wall -Wextra -Werror -pedantic
123.c: In function ‘gcd’:
123.c:6:1: error: control reaches end of non-void function [-Werror=return-type]
 }
 ^
cc1: all warnings being treated as errors

不幸的是,周围有各种各样的错误代码,这意味着 C 编译器默认情况下比真正需要的更宽松。另一个问题是,在 C 中省略 return 语句甚至都不是错误的——只是使用垃圾 return 值是。

Python 没有类似 C 的未定义行为,因此当您省略 return 语句时,函数 returns None 隐含地,您不不会得到一些随机垃圾,使您的损坏代码看起来好像有效。


更正确的函数定义应该是

int gcd(int a, int b)
{
    if(b == 0)
        return a;
    return gcd(b, a % b);
}

然而,也许这些参数应该是 unsigned int,这样您就不会认为这对于负数总是正确的。

C 中的代码具有未定义的行为,第二个代码路径(递归调用)上没有 return 语句。你很幸运 return 值总是保存在同一个寄存器中并且没有被覆盖,但不能保证,你可能会得到垃圾。

Python 明确将缺失的 return 路径视为 return None