I hope that this is not a duplicate, I apologise if so, but have done some googling and looking around stack overflow and not found anything as yet...
MCVE
I understand that if a function keeps calling itself, this can't keep happening indefinitely without a stack overflow, and so an error is raised after a certain limit. For example:
def foo():
return foo()
foo()
This gives rise to the following error:
RecursionError: maximum recursion depth exceeded
However, if I write a function such as the following:
def count(n):
if n == 0:
return 0
else:
return count(n-1)+1
count(1000)
I get a slightly different error:
RecursionError: maximum recursion depth exceeded in comparison
The question
What is the "in comparison" referring to in the above error. I guess what I'm asking is what is difference between these two situations, that gives rise to two different errors.
I played around with it and found some interesting results.
As we know:
def foo():
foo()
Gives rise to
RecursionError: maximum recursion depth exceeded
What I found was
def bar():
if False:
return 0
else:
bar()
def baz():
if True:
baz()
else:
return 0
Both bar()
and baz()
give rise to
RecursionError: maximum recursion depth exceeded
And then
def ding():
if 1 == 2:
return 0
else:
ding()
def dong():
if 1 != 2:
dong()
else:
return 0
Both ding()
and dong()
give rise to
RecursionError: maximum recursion depth exceeded in comparison
My intuition here is that python knows you are doing a comparison using the comparators =,!,<,>
and that this comparison never reaches the 'base case' condition (within the limits of the maximum depth). So python is letting you know that your comparison never converges to meet the condition.
This helpfulness starts to break down when you try
def oops():
if 1 == 2:
oops()
else:
oops()
But in the end python can only be so helpful with error messages.
When a RecursionError
is raised, the python interpreter may also offer you the context of the call that caused the error. This only serves for debugging, to give you a hint where in your code you should look in order to fix the problem.
See for example this circular str
-call setup that leads to a different message:
>>> 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
There is no documentation of this behaviour on the issue discussion where RecursionError
was introduced, but you can just search the cpython code for occurences of Py_EnterRecursiveCall. Then you can see the actual contexts that will be returned depending on where the error is raised:
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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With