よろずやIT
プログラミング

再帰(再帰関数)とは?自分自身を呼ぶ仕組みを、Pythonと図解で解説

執筆・監修:よろずやIT編集部|編集方針を見る

結論:まずここだけ読めばOK

詳しい手順・原因は、この下で解説しています。

プログラミングのイラスト

結論: 再帰は、関数が、自分自身を呼び出す書き方です。大きな問題を、同じ形の、より小さな問題に分けて解きます。必要なのは、**①これ以上は呼ばない「終了条件」**と、②呼ぶたびに終了条件へ近づくことの2つです。どちらかが欠けると、止まらずに呼び続けて、RecursionErrorになります。

再帰とは

「n の階乗(n!)」は、1からnまでを、すべて掛け合わせた数です。

「階乗を求める問題」が、「より小さな階乗を求める問題」の中に、入っています。この入れ子の構造を、そのままプログラムにしたのが、再帰です。

基本の形:階乗

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

print(factorial(3))   # 6

関数の基本は、関数とは、条件の書き方は、条件分岐(if文)とはをご覧ください。

動きを追う:factorial(3)

factorial(3)の呼び出しが深くなり、終了条件で止まって、結果が順に戻る流れを示した図解

  1. factorial(3) は、「3 × factorial(2)」を計算しようとして、factorial(2) を呼ぶ
  2. factorial(2) は、「2 × factorial(1)」を計算しようとして、factorial(1) を呼ぶ
  3. factorial(1) は、終了条件に当てはまるので、1を返す
  4. 結果が順に戻る:factorial(2) は 2 × 1 = 2、factorial(3) は 3 × 2 = 6

**「下へ呼び出して、上へ結果が戻る」**という二段構えが、再帰の動きです。

再帰に必要な2つと、エラー

終了条件と、問題を小さくして自分を呼ぶことの2つと、RecursionErrorが出た時の確認を示した図解

必要なもの 内容
① 終了条件 これ以上は、自分を呼ばずに、答えを返す
② 問題を小さくする 呼ぶたびに、終了条件へ近づく(例:n - 1)

RecursionError

def broken(n):
    return n * broken(n - 1)   # 終了条件がない

終了条件がないため、止まらずに呼び続けます。Pythonでは、呼び出しの深さに上限があり(既定で約1,000回)、超えると、次のエラーになります。

RecursionError: maximum recursion depth exceeded

エラーが出た時の確認

再帰が向く場面

「同じ形の問題が、中に入っている」構造に向きます。

場面 例
フォルダの構造 フォルダの中のフォルダを、すべてたどる
入れ子のデータ 階層のあるデータ(JSONとは)を、すべて調べる
分割して解く問題 大きな問題を、小さく分けて解く(アルゴリズムとは)

ループとの使い分け

再帰 ループ
向く構造 入れ子・階層 単純な繰り返し
分かりやすさ 慣れると簡潔。慣れないと追いにくい 流れが追いやすい
注意点 深さの上限、終了条件 無限ループ
速さ・メモリ 呼び出しが深いと、負担が大きい 軽い

同じ階乗は、ループでも書けます。

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

迷ったら、ループで書けるものは、ループで書くのが無難です。ループの基本は、ループ(繰り返し)とはをご覧ください。

再帰が遅くなる例:フィボナッチ

フィボナッチ数(1, 1, 2, 3, 5, 8, …)を、単純な再帰で求めると、同じ計算を何度も繰り返すため、数が大きくなると、急に遅くなります。

といった工夫で、改善できます。

まとめ

関連記事:ループ(繰り返し)とは、条件分岐(if文)とは、関数とは、アルゴリズムとは、デバッグとは

あわせて読みたい:スコープ(変数の有効範囲)とは

PRPython イラストで学ぶIT入門 Python初心者と新人SEのための実務につながる基礎学習ガイド【電子書籍】[ 高市 勇気 ]

Python イラストで学ぶIT入門 Python初心者と新人SEのための実務につながる基礎学習ガイド【電子書籍】[ 高市 勇気 ]

¥990

楽天で見る
SHAREXLINEはてブ

よくある質問

Q.再帰とループは、どちらを使えばいいですか?

A.単純に回数を繰り返すだけなら、ループのほうが分かりやすく、安全です。フォルダの中のフォルダや、入れ子になったデータのように、『同じ形の問題が、中に入っている』構造では、再帰のほうが自然に書けることがあります。再帰で書ける処理は、ループでも書けますが、書き方が複雑になる場合があります。

Q.RecursionErrorが出ました。どうすればいいですか?

A.再帰の深さが、上限を超えたというエラーです。Pythonでは、既定の上限が、約1,000回に設定されています。まず、終了条件が正しく書かれているか、呼ぶたびに値が終了条件へ近づいているかを確認します。問題がなければ、ループに書き換える方法があります。

Q.終了条件とは、何ですか?

A.『これ以上は、自分を呼ばずに、答えを返す』という条件です。階乗の例では、『nが1以下なら、1を返す』が終了条件です。終了条件がないと、永遠に自分を呼び続けてしまいます。

Q.再帰は、なぜ難しく感じるのですか?

A.実行の流れが、『下へ呼び出して、上へ結果が戻る』という二段構えで、頭の中で追いにくいためです。小さな値で、紙に書いて動きを追う練習が、理解の近道です。

Q.再帰が、遅くなることはありますか?

A.あります。たとえば、フィボナッチ数を単純な再帰で求めると、同じ計算を何度も繰り返して、急に遅くなります。計算結果を覚えておく工夫(メモ化)や、ループへの書き換えで、改善できます。

関連記事

最新のIT関連書籍 トップ10

PR / 楽天市場の売れ筋ランキングを定期的に取得しています。価格は変動する場合があるため、購入前に各ストアでご確認ください。