Select Language

AI Technology Community

3.6、Python再帰関数の例の詳細

再帰呼び出しは高度なプログラミング言語の基本的な特性であり、最初はLISP言語に現れました。Python言語も再帰呼び出しをサポートしています。再帰呼び出しを通じてコードを簡素化することができ、しかもコードを問題の数学的な記述と非常に一致させることができます。再帰呼び出しを使用しても一般的にコードの実行速度は向上しません。

再帰呼び出しとは

再帰呼び出しは特殊なネスト呼び出しであり、ある関数が自身を呼び出すか、他の関数を呼び出した後に再度自身を呼び出すことを指します。無限にネスト呼び出しすることはできないため、ある再帰関数には必ず少なくとも2つの分岐が存在します。1つはネストを終了し、直接的または間接的に自身を呼び出さない分岐で、もう1つはネストを続ける分岐です。

一般的に関数の入力パラメータによってどの分岐をたどるかを決定するため、再帰関数は一般的にパラメータを持っています。

再帰呼び出しの例

1、階乗の計算

最も一般的な再帰の使い方は整数の階乗を求めることです。例えば、2の階乗は1×2に等しく、3の階乗は1×2×3に等しいです。再帰的な方法を使わない場合、以下の方法で実装することができます。

>>> def get_factorial(n):                      # 階乗関数を定義
...     ret = i = 1
..     while i <= n:                           # 1からnまで順に乗算
...             ret = ret * I
...             i = i + 1
...     return ret                             # 戻り値を返す
...                                           # 階乗関数の定義終了
>>> get_factorial(3)                           # 3の階乗を求める
6
>>> get_factorial(10)                          # 10の階乗を求める
3628800

再帰的な方法を使う場合、以下のような評価方案を定義することができます。


n>1の場合、階乗関数自身を再帰的に呼び出すことができます。コードは以下の通りです。

>>> def get_factorial(n):                              # 階乗関数を定義
...     if n == 1:                                     # 再帰を終了する分岐
...         return 1
...     return n * get_factorial(n-1)   # 再帰呼び出し
...                                                   # 階乗関数の定義終了
>>> get_factorial(3)                                   # 3の階乗を求める
6
>>> get_factorial(10)                                  # 10の階乗を求める
3628800


再帰には再帰の深さに注意する必要があります。再帰は複数回の関数呼び出しを生み出し、関数呼び出しはコードのスタック領域を消費します。再帰の深さが大きすぎると、スタックオーバーフローが発生します。上記の階乗の例では、100000の階乗を計算すると、一般的なマシンではスタックオーバーフローの問題が発生します。以下に示します。

>>> get_factorial(100000)             # 100000の階乗を求める
Traceback (most recent call last):    # エラーメッセージ
File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in get_factorial
  File "<stdin>", line 4, in get_factorial
  File "<stdin>", line 4, in get_factorial
  [Previous line repeated 994 more times]
  File "<stdin>", line 2, in get_factorial
RecursionError: maximum recursion depth exceeded in comparison

デフォルトでは、関数呼び出しの深さの最大値は1000です。1000に達するか超えると、上記のエラーメッセージが表示されます。以下のコードでこのシステム設定を確認することができます。

>>> import sys
>>> sys.getrecursionlimit()   # 最大呼び出し深さを取得
1000                    # 現在の値は1000

このシステム値を変更したい場合は、sysモジュールのインターフェース関数を使用して実現することもできます。最大関数呼び出し深さを10000に設定したい場合は、以下のコードを使用して変更することができます。

>>> import sys
>>> sys.setrecursionlimit(10000)               # 最大呼び出し深さを設定

2、フィボナッチ数列

1、1、2、3、5、8、13、21、34…という数列があります。最初の要素と2番目の要素は1に等しく、他の要素はその前の2つの要素の和に等しいです。数学的な公式で表すと以下の通りです。


以下のコードで実装することができます。

>>> def fab(n):          # フィボナッチ数列を定義
...     if n in [1, 2]:  # nが1または2の場合
...         return 1
...     return fab(n-1)+fab(n-2)    # n>2の場合
...
>>> fab(1)                          # フィボナッチ数列の最初の要素
1
>>> fab(2)                          # フィボナッチ数列の2番目の要素
1
>>> fab(8)                          # フィボナッチ数列の8番目の要素
21
>>> fab(8)                          # フィボナッチ数列の9番目の要素
34

3、順列

入力されたリストについて、要素の位置を変えることで異なる値を得ることができます。順列とは、これらのすべての並び替えのリストを取得することです。一般的に、n個の要素のリストにはn!通りの並び替え方法があります。例えば、[1,2,3]には以下のような並び替え方法があります。

1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1

以下は再帰的な方法で実装された順列です。

>>> def sub_combination(left, right):  # leftは左側の処理待ちのリストを表す
...     if len(left) > 0:              # 処理が完了していない場合
...         for item in left:          # 処理が完了していない要素から1つ
post
Pythonの関数
2021-12-10 23:42:59join communtity
  • 6

    item of content
関数はコードの基本的なモジュールであり、特定の機能を実現し、他のコードから利用することができます。関数を使うことでコードのモジュール性が向上し、コードの組織化がより効率的になり、共同開発が促進されます。
現代のソフトウェア開発言語はすべて関数をサポートしており、関数をコードの最も基本的な単位と考えることができます。たとえ最もシンプルな「Hello, Python」コードでも、print() 関数の呼び出しに関数が関わっています。
この章では、関数の基本概念と使用方法について紹介します。具体的には、Pythonの関数の定義と使用方法、関数パラメータの使い方、よく使用される組み込み関数、そしてlambda関数や再帰に関する内容を含みます。