質問
これはばかげた質問のように聞こえるかもしれませんが、最後にプログラムしたのはアセンブラーでしたので、私の考えはずれているかもしれません:
そのような再帰関数:
def fac(n):
if n == 0:
return 1
else:
return n * fac(n - 1)
関数がn == 0に達したときに1を返さず、階乗である答えを返すのはなぜですか。アセンブラーでは、n == 0の場合のようになると考えています:
mov eax, 1
ret
上記のコードが機能する理由は、Pythonがその条件の前にスタックの最後の値を返すと思いますか?
解決
たとえば fac(5)
の場合、次のように考えてください:
return 5 * fac(4)
return 4 * fac(3)
return 3 * fac(2)
return 2 * fac(1)
return 1 * fac(0)
1
したがって、 1
は first の戻り値になりますが、 fac(1)
および fac(1)に返されます
は fac(2)
などに返されます。
他のヒント
n == 0の場合、しない 1を返します。その戻り値は、呼び出し元サイトからスタックからポップされます。これは、 n * fac(n-1)
。 1
に n
を掛けて返されます。
fac(0)を呼び出すと、1が返されます(0ではなく、質問のタイプミスだと思います)。 fac(1)を呼び出すと、else節に入り、そこで fac(0)
を呼び出します。これは1を返します。その後、n * 1(1)を計算し、それを返します。 fac(2)
を呼び出すと、else節にも移動します。ここで、 fac(1)
が呼び出され、上記のように1が返されるため、 n * fac(n-1)
は2になり、それが fac(2)
の戻り値になります。等々。それがあなたのために説明したことを願っています。
暗黙的に何も返されません-n = 0の場合、関数はifステートメントに入り、 return 1
ステートメントから直接1を返します。
ただし、これは「要因である回答」が表示される時点ではありません。ユーザーに返されます。代わりに、この値を
n * fac(n-1)
ブランチの途中にあるfac(1)によって呼び出される呼び出し関数。したがって、「1」を取得します。返され、 n * 1
を返します。これは、発信者に対して1です。それがfac(2)の場合、 n * 1
、または2をその発信者などに返します。
したがって、fac(5)は次のように翻訳されます:
fac(5) = 5 * fac(4) = 5 * (4 * fac(3) = 5 * (4* (3 * fac(2)) = 5 * (4* (3 * (2 * fac(1)) = 5 * (4* (3 * (2 * (1 * fac(0)) = 5*4*3*2*1*1
1つの値が各上位層を介して返された後にのみ、最初の呼び出し元に戻り、各段階での乗算により答えが得られます。
ジェームス、関数の最後の呼び出し(n == 0の場合)が返されるとき、それは呼び出しスタック上のfac(n)のいくつかのインスタンスの1つにすぎません。 print(fac(4))と言うと、スタックは本質的に次のようになります。
fac(0)
fac(1)
fac(2)
fac(3)
fac(4)
print()
fac(0)への最後の呼び出しは1を適切に返しますが、Pythonでは、fac(n)、fac(4)への最初の呼び出しの戻り値を要求しました。
「ret」が発生するループとは考えないでください。リターンは、保留中の実行の1つを単に終了します。