このエラーが発生する原因
Pythonはデフォルトでコールスタックを1000フレームに制限しています。関数が直接または連鎖的に自分自身を呼び出し、その制限に達する前に停止しない場合、次のエラーが発生します:
RecursionError: maximum recursion depth exceeded
ほとんどの場合、次の4つの状況が原因です:
- 基底ケースが全くない再帰関数
- 基底ケースはあるが、ロジックのバグにより到達しない
- 深くネストされたデータ — JSONツリー、XMLドキュメント、数百レベルのASTノード
- 誤って
__eq__や__repr__などの組み込みメソッドをオーバーライドして自分自身を呼び出す
トレースバックの読み方
トレースバックを見れば問題箇所は明らかです。同じ2〜3行が何百回も繰り返されます:
File "app.py", line 5, in factorial
return n * factorial(n - 1)
File "app.py", line 5, in factorial
return n * factorial(n - 1)
[Previous line repeated 996 more times]
この繰り返し行が問題の原因です。修正方法はなぜループし続けているかによります。
修正1 — 基底ケースの追加または修正
十中八九、これが実際の問題です。すべての再帰関数には連鎖を停止する条件が必要です。
問題のあるコード:
def factorial(n):
return n * factorial(n - 1) # 永遠に停止しない
修正後:
def factorial(n):
if n n)からO(n)に削減されます。
## 修正5 — __repr__と__eq__での誤った自己呼び出しを防ぐ
見落としやすい罠:`__repr__`を定義してその中で`f"{self}"`を使うと、そのフォーマット文字列が再び`__repr__`を呼び出します。無限ループになります。
悪い例 — 無限再帰
class Node: def repr(self): return f"Node({self})" # selfの__repr__を呼び出す!
良い例 — selfではなく値を参照する
class Node: def init(self, val): self.val = val def repr(self): return f"Node({self.val})"
同じ落とし穴が`__eq__`と`__hash__`にも存在します。どちらかが暗黙的にもう一方を呼び出すと、同じような無限ループが発生します。
## 修正の確認
エッジケース(ゼロ、負の値、以前クラッシュしていたサイズ)に対して関数を実行して確認します:
import sys print(sys.getrecursionlimit()) # 現在の制限を確認
result = factorial(999) print(result) # 大きな数値、RecursionErrorなし
制限を引き上げた場合、新しい境界付近をテスト
sys.setrecursionlimit(3000) result = factorial(2500) print("OK")
入力範囲全体で例外が発生しなければ、修正が成功しています。
## クイックリファレンス
- **基底ケースがない** → 終了条件を追加する
- **ロジックは正しいが入力が深い** → `sys.setrecursionlimit(N)`
- **本番/大規模データ** → ループと明示的なスタックで書き直す
- **重複するサブ問題** → `@lru_cache`を追加する
- **誤った自己呼び出し** → `__repr__`、`__eq__`、`__hash__`を確認する

