Python標準ライブラリのcontextlib.ExitStackを利用すると、コンテキストマネージャーを個別に管理する必要はなくなりスコープを抜けた際に一括で開放できるためコードの見通しが非常に良くなると思います。
ExitStackを使わないコード
def sample(): with (open("path","r") as f, open("path2","r") as f2, ): pass
個人的に見通しが良いと思っていません。
冒頭のwithに含められない場合には、ネストしてwithを利用する必要がありさらに可読性に難ありだと思っています。
ExitStackを使う場合
from contextlib import ExitStack def sample(): with ExitStack() as stack: f = stack.enter_context(open("path","r")) f2 = stack.enter_context(open("path2","r"))
with 文を改行するよりも見通しがよくなり、スコープの任意の場所で安全にインスタンス生成が可能となりましたが、このために関数全体with 文を適用してネストを深めるのもなんだかなぁな感じです。
デコレータでExitStackを隠蔽すればいいのでは?
from functools import wraps from contextlib import ExitStack def with_exit_stack(func): @wraps(func) def wrapper(*args, **kwargs): with ExitStack() as stack: # `ExitStack` を引数として渡す return func(*args, stack=stack, **kwargs) return wrapper @with_exit_stack def sample(stack: ExitStack): f = stack.enter_context(open("path","r")) f2 = stack.enter_context(open("path2","r")) # リソースは関数終了時に自動的に解放 sample()
関数を抜ける際にリソースが安全に開放され、ネストも深くならないのでこれでよさそうです。










