中学理科1625756 views
MathPython489968 views
小学社会308525 views
ヒストリア282760 views
中学英語808125 views
雑学1472443 views
小学算数1193669 views
数学講師2847003 views
中学社会666920 views
高校化学2912417 views
Help
Tools

English

Python の再帰関数と末尾再帰最適化の限界

再帰関数は自分自身を呼び出す関数です。階層構造やツリー構造の処理に適していますが、Python には末尾再帰最適化がないため、深い再帰には注意が必要です。

基本的な再帰

階乗を計算する例です。

def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))  # 120

再帰には「基底条件」(終了条件)が必須です。なければ無限ループになります。

末尾再帰とは

末尾再帰は、再帰呼び出しが関数の最後の処理になっている形式です。

def factorial_tail(n, acc=1):
    if n <= 1:
        return acc
    return factorial_tail(n - 1, acc * n)

一部の言語では、末尾再帰をループに変換する「末尾再帰最適化」が行われます。しかし Python はこの最適化を行いません。

Python の再帰制限

Python にはデフォルトで再帰の深さ制限があります。

import sys
print(sys.getrecursionlimit())  # 通常 1000

深い再帰は RecursionError を引き起こします。

factorial(1500)  # RecursionError

対処法

深い再帰が必要な場合は、ループに書き換えるのが一般的です。

def factorial_iter(n):
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result

再帰制限を変更することも可能ですが、スタックオーバーフローの危険があるため推奨されません。

sys.setrecursionlimit(3000)  # 非推奨

Python で再帰を使う際は、深さが限定的なケース(ツリー探索など)に留め、深い再帰にはループを使いましょう。