こんにちは,ティロといいます.
他人のソースコードを読んでいる際に,関数の上に@contextlib.contextmanagerがあり,
「???」となったのでコンテキストマネージャについて説明します.
コンテキストマネージャってなに?
まずコンテキストマネージャとは__enter__メソッドと__exit__メソッドを持つクラス(インスタンス)のことです.
with文と組み合わせて使います.
サンプルコードを見てください.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class hoge: def __enter__(self): print("enter") def __exit__(self, exc_type, exc_value, traceback): print("exit") hoge = hoge() with hoge: print("hoge") 実行結果 enter hoge exit |
with hogeで前処理として__enter__が呼ばれます.
with hoge内の処理が終わったら後処理として__exit__が実行されます.
_exit__の引数で渡される値は例外が発生した場合に役立ちます.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class hoge: def __enter__(self): print("enter") def __exit__(self, exc_type, exc_value, traceback): print("exit") print(exc_type) print(exc_value) print(traceback) return True hoge = hoge() with hoge: a = 1/0 print(a) 実行結果 enter exit <class 'ZeroDivisionError'> division by zero <traceback object at 0x7f1e5c852f50> |
return Trueにすると例外が発生した場合においても最後まで処理されます.
デコレータは関数を修飾するもの
関数の上にある@contextlib.contextmanagerはコンテキストマネージャをシンプルにしたものです.
まず@〜〜はデコレータといいます.
デコレータとはざっくりいうと関数を修飾するものです.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def increment(a): def inner(content): content += 1 return content return inner @increment def a(content): print(content) a(5) 実行結果 6 |
デコレートしたい関数の上に@デコレータ名を書きます.
デコレータは最初の行で宣言してます.その際,デコレートされる関数(ここでは a)を引数にします.
inner内で処理を記述します.
デコレータの詳しい説明はこちら
@contextlib.contextmanagerとは
@contextlib.contextmanagerはコンテキストマネージャのデコレータです.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from contextlib import contextmanager @contextmanager def hoge(): print('enter') yield print('exit') with hoge(): print('hoge') 実行結果 enter hoge exit |
サンプルコードのように__next__や__exit__を書く必要がありません.