Pythonで複数行のwith
を作成するきれいな方法は何ですか?単一のwith
内で複数のファイルを開きたいのですが、複数行で必要なのはそれだけです。このような:
class Dummy:
def __enter__(self): pass
def __exit__(self, type, value, traceback): pass
with Dummy() as a, Dummy() as b,
Dummy() as c:
pass
残念ながら、それはSyntaxError
です。だから私はこれを試しました:
with (Dummy() as a, Dummy() as b,
Dummy() as c):
pass
また、構文エラー。しかし、これはうまくいきました:
with Dummy() as a, Dummy() as b,\
Dummy() as c:
pass
しかし、コメントを付けたい場合はどうすればよいでしょうか?これは動作しません:
with Dummy() as a, Dummy() as b,\
# my comment explaining why I wanted Dummy() as c\
Dummy() as c:
pass
\
sの配置に明らかな変化もありません。
内部にコメントを許可する複数行のwith
ステートメントを作成するクリーンな方法はありますか?
このPython 3をタグ付けしている場合、コンテキストマネージャーにコメントを散在させる必要がある場合は、 contextlib.ExitStack
を使用します。
with ExitStack() as stack:
a = stack.enter_context(Dummy()) # Relevant comment
b = stack.enter_context(Dummy()) # Comment about b
c = stack.enter_context(Dummy()) # Further information
これは次と同等です
with Dummy() as a, Dummy() as b, Dummy() as c:
これには、各コンテキストマネージャーを個別に一覧表示する代わりに、ループでコンテキストマネージャーを生成できるという利点があります。ドキュメントには、ファイルの束を開きたい場合、リストにファイル名がある場合、次のことができる例を示しています
with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
コンテキストマネージャが非常に多くの画面スペースを必要とするため、それらの間にコメントを入れたい場合、おそらく何らかのループを使用するのに十分です。
デスレス氏がコメントで言及しているように、PyPIにはcontextlib2
という名前で contextlibバックポート があります。 Python 2)を使用している場合、バックポートのExitStack
の実装を使用できます。
これは私にとって最もきれいなようです:
with open('firstfile', 'r') as (f1 # first
), open('secondfile', 'r') as (f2 # second
):
pass
これは正確ではありませんが、これを行うことができます:
with Dummy() as a, Dummy() as b, (
#my comment
Dummy()) as c:
pass
構文エラーはありませんが、最もクリーンではありません。これを行うこともできます:
with Dummy() as a, Dummy() as b, Dummy(
#my comment
) as c:
pass
with
の途中にあるコメントを使用せずにこれを行う方法を見つけることを検討してください。
with
ステートメントの前、または行自体にコメントを追加することで、物事をシンプルで読みやすくします。
# my comment explaining why I wanted Dummy() as c
with Dummy() as a, Dummy() as b,\
Dummy() as c: # or add the comment here
pass
TigerhawkT3's answer に似ていますが、インデントを使用してもトリガーされません pycodestyle's error E124 :
with (
open('firstfile', 'r')) as f1, ( # first
open('secondfile', 'r')) as f2: # second
pass
IMOそれはまだいですが、少なくともリンターを通過します。