Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

with構文と前処理・後処理の話

だいぶ以前にwith構文と合わせて使えるcontextlibの話を扱いました。
shuzo-kino.hateblo.jp

当時はyield構文スゲー状態だったので、yieldに注目してましたが……後々から考えると開始と終了について明示的に書けるのが、本来のこの構文の強みだったみたいですね。
書いてるウチに訳がわからなくなるtry-finallyあたりの見通しが良くなるのは素晴らしい。

実際のところ

クラスに開始と終了を紐付ける

Fileオブジェクトをwith構文で読むと一々クローズしなくて良いですが
任意のクラスにもそういった挙動を実装することができます

class MyContextManager:
    def __enter__(self):
        print("開始時に実行")
        return self  # withで使用するオブジェクトを返す
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("終了時に実行(例外が発生しても必ず実行)")
        # ここで例外処理も可能

with MyContextManager() as cm:
    print("処理実行中")

contextlibをつかう

以前の記事でyieldが使えると鼻息を荒くした事例

from contextlib import contextmanager

@contextmanager
def my_context():
    try:
        print("前処理")
        yield "値"  # withブロックで使用する値
    finally:
        print("後処理(必ず実行)")

with my_context() as value:
    print(f"処理中: {value}")

過去記事では、この機能を使って前後をHTMLタグで閉じる方法を紹介しました
いまならURDF用にタグ綴じなんかに使えるかも……?