55

Python (v3.2.3) の学習を始めたばかりreturnで、この関数で奇妙な問題が発生しました。

def test(x):
    if x > 9 :
        test(x - 10)
    else:
        print('real value',x)
        return x

x = int(input())
y = test(x)
print('this should be real value',y)

実行すると、次のようになります。

45
real value 5
this should be real value None

しかし、私は期待しました:

45
real value 5
this should be real value 5

return xの外側に追加してifみましたが、デフォルトの入力値が得られました。誰でも仕組みを説明できますreturnか?

4

3 に答える 3

91

を呼び出しtest(45)ます。これは true かどうかをテストするため、結果を返さずに (45 - 10) を45 > 9呼び出します。最終的に呼び出されるまで、test(35)同じことがtest(25)andで起こります。test(15)test(5)

これは 'real value 5' を出力し、5 を返します。しかし、関数から結果を返すと、常にこの関数の直接の呼び出し元に結果が返されます。いくつかの呼び出しですぐに飛び出すことはありません。結局のところ、呼び出し元は、呼び出し元に何かを返す前に、返された結果で何かをしたいと思うかもしれませ。ただし、この場合test(5)は何も返さないだけです。他のすべての人は を呼び出しtest(x - 10)、それが戻るのを待ち、それが返すものを無視してから (暗黙的に) を返しNoneます。最も外側の呼び出しtest(45)はこれらのケースの 1 つであるため、得られるのはNoneです。

何が起こるかを視覚化する試みは次のとおりです。

test(45):
| test(35):
| | test(25):
| | | test(15):
| | | | test(5):
| | | | | print('real value',5)
| | | | | return 5 to test(15)
| | | | return None to test(25)
| | | return None to test(35)
| | return None to test(45)
| return None

test(5)インタープリターで呼び出していませんでしたtest(5)。別の関数呼び出し内から呼び出されました。したがって、からの戻りはその関数呼び出しtest(5)に行きます。これが自分自身を呼び出す関数であるという事実は、まったく関係ありません。コードが次のようになっている場合、まったく同じ結果が得られます。

def test45(x):
    if x > 9 :
        test35(x - 10)
    else:
        print('real value',x)
        return x

def test35(x):
    if x > 9 :
        test25(x - 10)
    else:
        print('real value',x)
        return x

def test25(x):
    if x > 9 :
        test15(x - 10)
    else:
        print('real value',x)
        return x

def test15(x):
    if x > 9 :
        test5(x - 10)
    else:
        print('real value',x)
        return x

def test5(x):
    if x > 9 :
        print 'No more tests :('
    else:
        print('real value',x)
        return x

'x=45' で呼び出す test(x) 関数は、 を呼び出すことと同じtest45(45)です。再帰が関係していないNone場合に が返されるべきであることは明らかです。まあ、再帰が関係している場合、何も変わりません。ステートメントは、再帰的に呼び出された関数から戻るかどうかを認識も気にもせず、どちらの場合もまったく同じように動作します。return

実際、再帰は「特別な」ものではありません。通常の関数呼び出しとまったく同じように動作します。呼び出したものから引数を介して情報を受け取り、呼び出したものに返すことで情報を返します。何かを返さない場合 (おそらく の 1 つのアームでのみif)、Noneそのブランチで他の関数を呼び出すかどうかに関係なく、何かを呼び出した場合にその関数が返すものに関係なく、呼び出し元に返されます。呼び出す関数がたまたま内部にある同じ関数であるかどうかに関係なく。

于 2012-07-06T08:06:06.830 に答える
28

return はインデントされているため、else ブランチでのみ実行されます。最初の分岐が発生した場合、関数は暗黙的に None を返します。

これをに変更する必要があります

return test(x-10)
于 2012-07-06T05:13:17.553 に答える
5

のときに値を返すのを忘れましたx > 9。戻り値がなければ、関数は "return" しNoneます。

于 2012-07-06T05:13:45.320 に答える