在递归函数中返回中间值是 Python 的怪癖吗?

更新:让我澄清一下究竟是什么如此令人困惑。如果我添加这样的打印语句:


    def recur(lis, json, target):

        if lis[0] == target:

            print(json[tagert])

            return json[target]

        else:

            recur(lis[1:], json[lis[0]], target)

我的打印语句将显示 JSON 的预期值。我不知道如何表达这句话。鉴于 return 语句之前的行给出了我期望的结果(else 中没有 return 语句)为什么 else 中的 return 语句是必要的?


对于那些坚持反对这一点的人,我已经多次查看了有关缺少 return 语句的问题。其中任何一个从未得到回答的是为什么需要返回。随心所欲地对我投反对票,但至少要明白你在投反对票一个好问题。我认为这个社区正在成熟,但显然没有。


因此,我查看了几个与我的标题相同的问题,但我仍然不太明白为什么会这样。


如果我有这样的递归函数:


def recur(lis, json, target):

    if lis[0] == target:

        return json[target]

    else:

        return recur(lis[1:], json[lis[0]], target)

我按预期获得了返回值。


但是如果我不在 else 语句中返回 the,我会得到一个 None:


def recur(lis, json, target):

    if lis[0] == target:

        return json[target]

    else:

        recur(lis[1:], json[lis[0]], target)

>>> final_json = recur(my_list, my_json, 'ID')

>>> print(final_json)   

None

这是特定于 Python 的吗?我有点生疏,但我似乎记得像 Haskell 这样的语言更优雅地处理这个问题,我相信,我不需要返回递归调用的值。这对我来说更有意义 - 我不需要所有中间值,因为我在堆栈的每个级别传递我的函数所需的所有值。我在这里缺少什么?


ABOUTYOU
浏览 190回答 3
3回答

倚天杖

我能想到的最好的证明方法是比较一个非常简单的递归递归函数,在几种不同的语言中。我选择的函数将计算整数的阶乘。(一个非负数,为了简单起见,如果出现负整数、浮点数或一些愚蠢的东西,我不会尝试执行任何验证来阻止函数爆炸。)首先,在 Python 中:def factorial(n):    if (n == 0):        return 1    return n * factorial(n-1)所以在这里你有“返回的中间值”,这似乎是你声称的似乎是 Python 独有的。(当然,您不是返回递归调用本身的结果,而是对其执行的简单操作 - 但这不会改变情况,除非我完全误解了。您仍在返回值,以便用这个“中间结果”做一些事情。)那么让我们来看看如何在 Javascript 中做同样的事情。(是的,两种语言都有更优雅的方法来做到这一点,但我试图保持简单和严格的可比性。)function factorial(n) {    if (n == 0) {       return 1;    }    return n * factorial(n-1);}我希望你会同意,撇开基本语法上的细微差别,JS 版本与上面的 Python 版本相同。特别是,两者都做“返回中间值”的事情。我可以在 PHP 中编写完全相同的东西,或者(虽然我对这些语言不太熟悉)我认为在 C/C++/C#/Java 中,它会再次非常相同。现在,如果我们最终来到 Haskell,它实际上是一种与上述所有语言完全不同的语言,让我们看看如何定义相同的函数:factorial :: Integer -> Integerfactorial n    | n==0 = 1    | otherwise = n * factorial (n-1)是的,这里没有明确的 return 语句。但这只是因为 Haskell 函数是必须始终产生一个值的“纯”函数,因此在一些更复杂的代码的末尾,您只需定义它的结果,而不是使用明确的语句来告诉您该值是什么在每个可能的输入上。当然,您可以并且经常使用组合和其他高阶操作以“无点”风格更抽象地定义函数 - 这是函数式编程的好处之一。但归根结底,在 Haskell 中,函数最终是根据给定输入产生的输出来定义的——这实际上是基本的,这就是“函数”这个词在数学中的含义,以及它在数学中的含义纯函数式语言。(与单纯的“过程”相反,一个可重用的代码块可能会或可能不会产生一个值,就像在大多数过程语言(如 JS、Python 和其他语言)中一样。)所以换句话说,上面仍然“返回中间值”。将=在本例中的最后一行标志是否工作return在其他语言的语句。因此,如果我在一个非常简单的话题上讨论了太久,我深表歉意——我仍然不确定您的困惑在哪里。但我希望这能帮助你克服它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python