web-dev-qa-db-ja.com

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

これは、異常に動作するコードです。これは、私が書いた動作の単純化されたバージョンです。これはまだ奇妙な動作を示しており、なぜこれが発生しているのかについていくつかの具体的な質問がありました。

Windows 7ではPython 2.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が6 w/4または5ではなく6を印刷するのはなぜですか?
72
Kyle Owens

finally文はguaranteedであるためです(まあ、停電やPythonの制御の及ばないものを想定しています)。つまり、関数が戻る前に、異なる値を返すfinallyブロックを実行する必要があります。

Pythonドキュメント 状態:

Try ... finallyステートメントのtryスイートでreturn、break、continueステートメントが実行されると、finally節も「途中で」実行されます。continueステートメントはfinally節では無効です。 (理由は現在の実装の問題です。この制限は将来解除される可能性があります)。

これは、戻ろうとするとfinallyブロックが呼び出され、それが持っていたはずの値ではなく、その値を返すことを意味します。

105
Gareth Latty

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

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

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

5
Fred Huang