奇妙なTry-Except-Else-最後にReturnステートメントを使用した動作


88

これは、特殊に動作しているコードです。これは、私が書いた動作の簡略版です。これはまだ奇妙な振る舞いを示しており、なぜこれが起こっているのかについていくつかの具体的な質問がありました。

私はWindows7でPython2.6.6を使用しています。

def demo1():
    try:
        raise RuntimeError,"To Force Issue"
    except:
        return 1
    else:
        return 2
    finally:
        return 3

def demo2():
    try:
        try:
            raise RuntimeError,"To Force Issue"
        except:
            return 1
        else:
            return 2
        finally:
            return 3
    except:
        print 4
    else:
        print 5
    finally:
        print 6

結果:

>>> print demo1()
3
>>> print demo2()
6
3
  • デモ1が1ではなく3を返すのはなぜですか?
  • デモ2が4または5で6を印刷する代わりに6を印刷するのはなぜですか?

回答:


124

finallyステートメントは実行れることが保証されているためです(まあ、停電やPythonの制御外の何かがないと仮定します)。これは、関数が戻る前に、別の値を返すfinallyブロックを実行する必要があることを意味します。

Pythonのドキュメントの状態:

try…finallyステートメントのtryスイートでreturn、break、またはcontinueステートメントが実行されると、finally節も「終了時に」実行されます。

関数の戻り値は、最後に実行されたreturnステートメントによって決定されます。finish句は常に実行されるため、finally句で実行されるreturnステートメントは、常に最後に実行されるステートメントになります。

つまり、戻ろうとすると、finallyブロックが呼び出され、本来の値ではなく、その値が返されます。


4
2番目の例で5が印刷されないのはなぜですか?これはまだよく説明されていないと思います。戻り値はよく答えられていますが、2番目の例の5が印刷されないのはなぜですか
Joran Beasley

5
ああ、私はそれを最初の試みでのリターンが最終的にすぐに外側にジャンプすることを理解したと思います
Joran Beasley

2
まさに、finallyブロックは常に実行されるからです。
Gareth Latty 2012年

2
デモ2では、なぜネストされたfinallyを実行し、最後に外側にキックアウトしてから、ネストされたfinallyに戻って、単に外側からNoneを返すのではなく、リターンを終了するのですか?
カイルオーエンス

1
ときなのでreturn文が呼ばれ、任意のオープンのためのPythonチェックfinally必要句が実行される(上記の引用を参照)。
Gareth Latty 2012年

6

実行順序は次のとおりです。

  1. すべてを正常にブロックしてみてください->最後にブロック->機能が終了します
  2. ブロックを実行して例外Aに入る->最後にブロック->関数が終了する
  3. ブロックを試行して戻り値を作成し、returnを呼び出します->最後にブロック->ポップアップの戻り値->関数が終了します

したがって、finallyブロックに戻ると、事前に手順が終了します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.