Day19再帰関数

再帰関数


関数内、あなたは他の関数を呼び出すことができます。関数が自分自身の中に自分自身を呼び出す場合は、この関数は再帰関数です。

例えば、我々は階乗を計算n! = 1 x 2 x 3 x ... x n、機能fact(n)表現を、それを見ることができます。

事実(N)= N!= 1×2×3×... X(N-1)XN =(N-1)!XN =事実(N-1)XN

だから、fact(n)それはのように表すことができるn x fact(n-1)、N = 1は、唯一の特別な処理を必要とします。

だから、fact(n)書き込み再帰的な方法は、使用することです。

def fact(n):
    if n==1: return 1 return n * fact(n - 1) 

上記は、再帰関数です。あなたは試すことができます。

>>> fact(1)
1
>>> fact(5) 120 >>> fact(100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 

我々は計算するとfact(5)、我々は次のように関数の定義が計算されて見ることができます。

===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120

利点は、単純な再帰関数、明確なロジックを定義することです。理論的には、すべての再帰関数は、循環方式で書き込むことができますが、良いとして再帰ループロジックが明確でないとして。

再帰関数は、スタックオーバーフローを避けるように注意する必要があります。コンピュータでは、関数呼び出しが、このデータ構造スタック(スタック)を介して達成されるたびにスタックへの関数呼び出しスタックフレームが1だけ増加され、各時間関数戻り、スタックは、一つのスタックフレームを減少します。スタックのサイズは無制限ではないので、あまりにも再帰呼び出しの数は、スタックオーバーフローを引き起こす可能性があります。あなたは試すことができますfact(1000)

>>> fact(1000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in fact ... File "<stdin>", line 4, in fact RuntimeError: maximum recursion depth exceeded in comparison 

再帰呼び出しスタックオーバーフローをすることによって解決されるテール再帰特殊尾再帰関数も可能であるように、最適化末尾再帰実際にサイクルの効果は同じであるので、サイクル。

関数が戻るには、自分自身を自分自身を呼び出し、そして時に、return文が式を含めることはできません、末尾再帰手段。このように、コンパイラまたはあなたは、最適化末尾再帰に自分自身への再帰呼び出しを行うことができ、インタプリタ、唯一のスタックフレームを占有回数に関係なく、スタックオーバーフローの状況が発生しません。

上記fact(n)に起因する機能return n * fact(n - 1)乗算式の導入、それは末尾再帰ではありません。末尾再帰的方法を変更するためには、もう少しコードを必要とする各工程の生成物は、再帰関数に渡さなければならない主です。

def fact(n):
    return fact_iter(n, 1) def fact_iter(num, product): if num == 1: return product return fact_iter(num - 1, num * product) 

見ることができますreturn fact_iter(num - 1, num * product)再帰関数自体を返すのみ、num - 1およびnum * product関数呼び出しが関数呼び出しには影響しません前に評価されます。

fact(5)対応するfact_iter(5, 1)次のように電話を:

===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20) ===> fact_iter(2, 60) ===> fact_iter(1, 120) ===> 120 

場合は末尾再帰呼び出し、最適化された場合、スタックが成長しないため、どんなにコールは、スタックオーバーフローが発生することはありません何回。

残念ながら、ほとんどのプログラミング言語は、末尾再帰のために最適化されていない、Pythonインタプリタは、最適化をしなかったので、でも、上記のことをfact(n)末尾再帰的に機能は、スタックオーバーフローにつながることができます。

概要

再帰関数を使用する利点は欠点が深すぎるスタックオーバーフローの呼び出しを引き起こす可能性があり、シンプルかつ明確なロジックです。

言語防止の末尾再帰の最適化のために末尾再帰を経由してスタックオーバーフロー。末尾再帰ループと、実際にはループサイクルプログラミング言語が存在しない、と同等ですが唯一の末尾再帰を介して達成することができます。

標準のPythonインタプリタは、任意の再帰関数のスタックオーバーフローの問題が存在するために末尾再帰が最適化されませんでした。

おすすめ

転載: www.cnblogs.com/AaronY/p/12571838.html