RecursionError:比较超过最大递归深度
Posted
技术标签:
【中文标题】RecursionError:比较超过最大递归深度【英文标题】:RecursionError: maximum recursion depth exceeded in comparison 【发布时间】:2019-03-23 04:57:30 【问题描述】:我希望这不是重复的,如果是这样,我深表歉意,但是已经进行了一些谷歌搜索并查看了堆栈溢出,但还没有找到任何东西......
MCVE
我知道如果一个函数不断地调用自己,这不可能在没有堆栈溢出的情况下无限期地发生,因此在一定限制后会引发错误。例如:
def foo():
return foo()
foo()
这会导致以下错误:
RecursionError: maximum recursion depth exceeded
但是,如果我编写如下函数:
def count(n):
if n == 0:
return 0
else:
return count(n-1)+1
count(1000)
我得到一个稍微不同的错误:
RecursionError: maximum recursion depth exceeded in comparison
问题
上述错误中的“比较”指的是什么。我想我要问的是这两种情况有什么区别,这会导致两种不同的错误。
【问题讨论】:
递归深度在1000左右,所以值太大了。 只是猜测:比较的是n==0
,错误信息告诉我们这是一个条件递归。
表示比较n == 0
时发生了堆栈溢出。有什么大不了的?
【参考方案1】:
当出现RecursionError
时,python 解释器还可能会为您提供导致错误的调用的上下文。这仅用于调试,提示您应该在代码中的哪个位置查找以解决问题。
例如,请参阅此循环 str
-call setup,它会导致不同的消息:
>>> 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
在引入RecursionError
的the issue discussion 上没有此行为的文档,但您可以搜索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
【讨论】:
感谢您提供如此全面的回答。我认为我对实际递归深度的概念可能不正确?澄清一下: if 语句会增加递归深度吗?例如 1000 个嵌套的 if 语句会引发类似的错误吗? 不,RecursionError
s 仅在解释器找到循环时发生,这意味着同一个函数被无限调用。
好的。谢谢你。我想我很困惑为什么RecursionError
出现在比较中。如果在比较之前我的函数中有其他行,我仍然会收到错误in comparison
。与之前的其他行相比,它有什么特别之处?为什么函数调用次数过多时没有出现错误?
python 可以为您提供的关于错误发生位置的提示数量有限。实现递归错误的人决定如果它发生在包含比较的 if-else 块中,则将其打印为上下文。
存在循环时引发 RecursionError 是不正确的。当堆栈上的函数调用过多时,会引发 RecursionError。 n == 0
调用一个函数 (__eq__
),该函数导致您的程序达到堆栈限制。 Python 检测到这一点,并打印一条信息性错误消息。【参考方案2】:
我尝试了一下,发现了一些有趣的结果。
据我们所知:
def foo():
foo()
引起
RecursionError: maximum recursion depth exceeded
我发现的是
def bar():
if False:
return 0
else:
bar()
def baz():
if True:
baz()
else:
return 0
bar()
和 baz()
都会产生
RecursionError: maximum recursion depth exceeded
然后
def ding():
if 1 == 2:
return 0
else:
ding()
def dong():
if 1 != 2:
dong()
else:
return 0
ding()
和 dong()
都会产生
RecursionError: maximum recursion depth exceeded in comparison
我的直觉是,python 知道您正在使用比较器 =,!,<,>
进行比较,并且这种比较永远不会达到“基本情况”条件(在最大深度的范围内)。所以 python 让你知道你的比较永远不会收敛到满足条件。
当您尝试时,这种帮助开始失效
def oops():
if 1 == 2:
oops()
else:
oops()
但最终python只能对错误消息有帮助。
【讨论】:
以上是关于RecursionError:比较超过最大递归深度的主要内容,如果未能解决你的问题,请参考以下文章
Python - RecursionError:比较错误中超出了最大递归深度[重复]