web-dev-qa-db-ja.com

RecursionError:比較で最大再帰深度を超えました

私はこれが重複していないことを願っています、もしそうなら謝罪しますが、いくつかのグーグルとスタックオーバーフローを見て、まだ何も見つかりませんでした...

[〜#〜] 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

質問

上記のエラーで言及されている「比較」とは何ですか。私が尋ねているのは、これらの2つの状況の違いであり、2つの異なるエラーが発生することです。

9
Tim

RecursionErrorが発生すると、pythonインタープリターはエラーの原因となった呼び出しのコンテキストも提供する場合があります。これはデバッグの際にのみ役立ちます。問題を修正するためにコードを確認する必要があります。

たとえば、異なるメッセージにつながるこの循環str- callセットアップを参照してください。

>>> 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が導入されましたが、この動作のドキュメントはありませんが、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
6
Arne

私はそれで遊んで、いくつかの興味深い結果を見つけました。

みなさんご存じのとおり:

_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はエラーメッセージでのみ非常に役立ちます。

2
Jake