web-dev-qa-db-ja.com

Pythonステートメント付きの複数行

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ステートメントを作成するクリーンな方法はありますか?

40
Justin

この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の実装を使用できます。

44
user2357112

これは私にとって最もきれいなようです:

with open('firstfile', 'r') as (f1 # first
  ), open('secondfile', 'r') as (f2 # second
  ):
    pass
13
TigerhawkT3

これは正確ではありませんが、これを行うことができます:

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の途中にあるコメントを使用せずにこれを行う方法を見つけることを検討してください。

2
Justin

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
1
MiniQuark

TigerhawkT3's answer に似ていますが、インデントを使用してもトリガーされません pycodestyle's error E124

with (
        open('firstfile', 'r')) as f1, (  # first
        open('secondfile', 'r')) as f2:  # second
    pass

IMOそれはまだいですが、少なくともリンターを通過します。

0
wjandrea