blank page

プログラミングなどについて書きます

pythonのwith文を勉強する part2

nve3pd.hatenablog.com

この記事の続きを書いています.

ここでいうpythonはpython3のお話です.
クリスマスなんてものはなかった:cry:

withのブロックの中で例外が起こったら...

スイートが例外によって終了されたのなら、その例外の型、値、トレースバックが exit() に引数として渡されます。そうでなければ、 3 つの None 引数が与えられます。
スイートが例外により終了され、 exit() メソッドからの戻り値が偽(false)ならば、例外が再送出されます。この戻り値が真(true)ならば例外は抑制され、実行は with 文の次の文から続きます。
もしそのスイートが例外でない何らかの理由で終了した場合、その exit() からの戻り値は無視されて、実行は発生した終了の種類に応じた通常の位置から継続します。

試してみる

class Test_with:
    def __init__(self):
        print("__init__")

    def __enter__(self):
        print("__enter__")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("exc_type: ", exc_type)
        print("exc_value: ", exc_value)
        print("traceback: ", traceback)
        print("__exit__")
        return True
        #return False

    def __del__(self):  # ついでに書いた
        print("__del__")

    def say(self):
        print("Hello!")


def main():
    print("*** start main function ***")
    with Test_with() as test:
        print("test: ", test)
        print("*** start `with` ***")
        test.say()
        raise ValueError(int)
        print("*** end `with` ***")
    print("*** end main function ***")


if __name__ == "__main__":
    main()

出力結果

__exit__がTrueを返した場合

*** start main function ***
__init__
__enter__
test:  <__main__.Test_with object at 0x7f0d1adf1b70>
*** start `with` ***
Hello!
exc_type:  <class 'ValueError'>
exc_value:  <class 'int'>
traceback:  <traceback object at 0x7f0d1adf7988>
__exit__
*** end main function ***
__del__
#### 

__exit__がFalseを返した場合

*** start main function ***
__init__
__enter__
test:  <__main__.Test_with object at 0x7fe8636ddb70>
*** start `with` ***
Hello!
exc_type:  <class 'ValueError'>
exc_value:  <class 'int'>
traceback:  <traceback object at 0x7fe8636e3988>
__exit__
Traceback (most recent call last):
  File "hoge.py", line 36, in <module>
    main()
  File "hoge.py", line 30, in main
    raise ValueError(int)
ValueError: <class 'int'>
__del__

追いかけます

スイートが例外によって終了されたのなら、その例外の型、値、トレースバックが exit() に引数として渡されます。そうでなければ、 3 つの None 引数が与えられます。そうでなければ、 3 つの None 引数が与えられます。

例外が発生すると __exit__ の引数に渡されているのが出力結果からわかります.
また,例外を発生させていない場合は前回の記事をみてわかる通りNoneが入っていますね.

スイートが例外により終了され、 exit() メソッドからの戻り値が偽(false)ならば、例外が再送出されます。

__exit__ がFalseを返した時はexitを抜けたあとに例外が発生しているのがわかりますね.

戻り値が真(true)ならば例外は抑制され、実行は with 文の次の文から続きます

__exit__がTrueを返した時は, 例外が消えてwith文の次の文から実行されて言ってるのがわかります.

もしそのスイートが例外でない何らかの理由で終了した場合、その exit() からの戻り値は無視されて、実行は発生した終了の種類に応じた通常の位置から継続します。

らしいです.

最後に

ここはどう使っていくのがいいのかがあまりイメージできていないので誰かおしえてもらえると幸いです.
あと,前回の記事に比べてだいぶ雑な感じになってしまい申し訳ないです:sorry:

参考文献

8. 複合文 (compound statement) — Python 3.6.3 ドキュメント

5. 組み込み例外 — Python 3.6.3 ドキュメント

3. データモデル — Python 3.6.3 ドキュメント