RecursionError:比较时超出了最大递归深度

Tim*_*Tim 9 python recursion python-3.x

我希望这不是重复,如果是这样,我道歉,但已经做了一些谷歌搜索,并查看堆栈溢出,还没有找到任何东西...

MCVE

我理解,如果一个函数不断调用自身,这不会无限期地发生而没有堆栈溢出,因此在一定限制之后会引发错误.例如:

def foo():
    return foo()

foo()
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误:

RecursionError: maximum recursion depth exceeded
Run Code Online (Sandbox Code Playgroud)

但是,如果我编写如下函数:

def count(n):
    if n == 0:
        return 0
    else:
        return count(n-1)+1

count(1000)
Run Code Online (Sandbox Code Playgroud)

我得到一个稍微不同的错误:

RecursionError: maximum recursion depth exceeded in comparison
Run Code Online (Sandbox Code Playgroud)

这个问题

在上述错误中引用的"比较"是什么.我想我要问的是这两种情况之间有什么区别,这会导致两种不同的错误.

Jak*_*ake 7

我尝试了一下并发现了一些有趣的结果。

据我们所知:

def foo():
    foo()
Run Code Online (Sandbox Code Playgroud)

引起

RecursionError: maximum recursion depth exceeded
Run Code Online (Sandbox Code Playgroud)

我发现的是

def bar():
    if False:
        return 0
    else:
        bar()

def baz():
    if True:
        baz()
    else:
        return 0
Run Code Online (Sandbox Code Playgroud)

两者bar()baz()产生

RecursionError: maximum recursion depth exceeded
Run Code Online (Sandbox Code Playgroud)

进而

def ding():
    if 1 == 2:
        return 0
    else:
        ding()

def dong():
    if 1 != 2:
        dong()
    else:
        return 0
Run Code Online (Sandbox Code Playgroud)

两者ding()dong()产生

RecursionError: maximum recursion depth exceeded in comparison
Run Code Online (Sandbox Code Playgroud)

我的直觉是,Python 知道您正在使用比较器进行比较=,!,<,>,并且该比较永远不会达到“基本情况”条件(在最大深度的限制内)。所以 python 让你知道你的比较永远不会收敛以满足条件。

当你尝试时,这种帮助就会开始崩溃

def oops():
    if 1 == 2:
        oops()
    else:
        oops()
Run Code Online (Sandbox Code Playgroud)

但归根结底,Python 对错误消息的帮助有限。


Arn*_*rne 6

RecursionError引发a时,python解释器还可以为您提供导致错误的调用的上下文.这仅用于调试,为您提供一个提示,在您的代码中您应该查看哪些内容以解决问题.

例如,请参阅此循环str调用设置,该消息会导致不同的消息:

>>> class A:
...     def __str__(self):
...         return str(self.parent)
>>> a = A()
>>> a.parent = a
>>> str(a)
RecursionError: maximum recursion depth exceeded while calling a Python object
Run Code Online (Sandbox Code Playgroud)

在引入的问题讨论中没有关于此行为的文档RecursionError,但您可以只搜索cpython代码以查找Py_EnterRecursiveCall的出现.然后,您可以根据引发错误的位置查看将返回的实际上下文:

Py_EnterRecursiveCall(" while encoding a JSON object")
Py_EnterRecursiveCall(" while pickling an object")
Py_EnterRecursiveCall(" in __instancecheck__")
Py_EnterRecursiveCall(" in __subclasscheck__")
Py_EnterRecursiveCall(" in comparison")
Py_EnterRecursiveCall(" while getting the repr of an object")
Py_EnterRecursiveCall(" while getting the str of an object")
Py_EnterRecursiveCall(" while calling a Python object")
Py_EnterRecursiveCall("while processing _as_parameter_") # sic
# .. and some more that I might have missed
Run Code Online (Sandbox Code Playgroud)

  • 当有一个循环时,引发RecursionError是不正确的.当堆栈上有太多函数调用时,抛出RecursionError.`n == 0`调用一个函数([`__eq__`](https://docs.python.org/3/reference/datamodel.html#object.__eq__)),该函数导致你的程序命中堆栈限制.Python检测到这一点,并打印出信息性的错误消息. (3认同)