Подтвердить что ты не робот

Многострочный Python с инструкцией

Что такое чистый способ создания многострочного with в python? Я хочу открыть несколько файлов внутри одного 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, который позволяет делать комментарии внутри него?

4b9b3361

Ответ 1

Учитывая, что вы пометили этот 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. Если вы на Python 2, вы можете использовать реализацию backport ExitStack.

Ответ 2

Это кажется мне самым утонченным:

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

Ответ 3

Это не совсем чисто, но вы можете сделать это:

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.

Ответ 4

Я бы сделал все просто и читабельно, добавив комментарий перед оператором 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

Ответ 5

Как и ответ TigerhawkT3, но с отступом, который не вызывает ошибку pycodestyle E124:

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

ИМО все еще безобразно, но, по крайней мере, проходит мимо.