Python|再帰関数の作り方と注意点

1. はじめに

Pythonの関数を学び始めた方にとって、次のステップとして登場するのが再帰関数です。
再帰関数とは、自分自身を呼び出す関数のことで、繰り返し処理をシンプルに記述できるメリットがあります。
本記事では、Python|再帰関数の作り方と注意点をテーマに、基礎から実践的な使い方までを丁寧に解説します。

再帰関数を使いこなすことで、例えば「階乗の計算」や「フィボナッチ数列」「ファイル階層の探索」など、ループでは書きにくい処理をスッキリと表現できます。

コード例と実行結果を交えてわかりやすく紹介しますので、初心者〜中級者の方はぜひ最後までご覧ください。

 

2. Pythonの再帰関数とは?

再帰関数の基本構文

再帰関数とは、「関数の中でその関数自身を呼び出す関数」のことです。Pythonでは以下のように記述します。

def recursive_function():
    # 基本処理
    if 条件:
        return 結果
    else:
        return recursive_function()  # 自分自身を呼び出す

実際に、整数の階乗(n!)を求める関数で例を見てみましょう。

階乗を再帰で求める

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

print(factorial(5))

実行結果:

120

このように、関数内で自分自身を呼び出しながら条件が満たされた時に終了するのが、再帰関数の基本的な仕組みです。

 

3. よくある使い方・応用例

フィボナッチ数列を求める再帰関数

フィボナッチ数列も再帰処理の代表例です。n番目のフィボナッチ数を求める関数は以下のように書けます。

def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

for i in range(10):
    print(fibonacci(i), end=" ")

実行結果:

0 1 1 2 3 5 8 13 21 34

このように、再帰を使えば繰り返しのロジックをシンプルに記述できます。
ただし、フィボナッチのように重複呼び出しが多いケースではパフォーマンスが低下するため、後述の注意点で対処法を紹介します。

実務でも使える!ディレクトリの再帰探索

ファイルシステムの操作では、osモジュールと組み合わせて再帰処理を使うことがあります。

import os

def list_files(path):
    for entry in os.listdir(path):
        full_path = os.path.join(path, entry)
        if os.path.isdir(full_path):
            list_files(full_path)  # 再帰的にディレクトリを探索
        else:
            print(full_path)

# 任意のディレクトリを指定
list_files("./test")

実行結果:

./test/file1.txt  
./test/dir1/file2.txt  
./test/dir2/file3.txt

このように、ネストされた構造を探索する処理では、再帰関数はとても強力なツールになります。

 

4. 再帰関数の注意点・エラー対策

無限再帰に注意

再帰関数では終了条件(ベースケース)を必ず設定しないと、RecursionError(最大再帰深度の超過)になります。

def bad_recursive(n):
    # 終了条件がないため、無限ループになる
    return bad_recursive(n + 1)

bad_recursive(0)

実行結果:

RecursionError: maximum recursion depth exceeded

このようなエラーを防ぐために、終了条件を明確に設定し、再帰の回数が深くなりすぎないように気をつけましょう。

再帰の深さに制限がある

Pythonには再帰の深さ(デフォルトで約1000)に制限があります。深い再帰が必要な場合は、ループやスタックを使った書き換えも検討しましょう。

パフォーマンスの問題と対処

前述のフィボナッチの例のように、同じ値を何度も計算するような再帰ではパフォーマンスが悪化します。
このような場合は、functools.lru_cacheを使ってキャッシュを活用するのがおすすめです。

from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(35))

実行結果:

9227465

キャッシュを使うことで、計算の重複を回避して大幅に高速化できます。

 

5. まとめ

今回は「Python|再帰関数の作り方と注意点」というテーマで、以下の内容を学びました。

  • 再帰関数の基本構文と仕組み
  • 階乗・フィボナッチ・ディレクトリ探索の応用例
  • 無限再帰やパフォーマンスに関する注意点と対処法

再帰関数は最初は難しく感じるかもしれませんが、「終了条件を正しく設ける」というポイントさえ守れば強力な武器になります。
特に、ネスト構造の探索やアルゴリズムの実装では欠かせない考え方です。

学習のコツとしては、まずは「再帰しないと解きにくい問題」で実際に使ってみること。
そうすることで、ループとは違う「再帰の思考」に慣れていくことができます。

ぜひ今後の学習や実務の中でも、再帰関数をうまく活用してみてください!

タイトルとURLをコピーしました