簡體   English   中英

Python 多行帶語句

[英]Python multi-line with statement

什么是干凈的方法來創建一個多行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陳述,讓里面的意見?

鑒於您已經標記了這個 Python 3,如果您需要用上下文管理器散布注釋,我會使用contextlib.ExitStack

from contextlib import 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]

如果您的上下文管理器占用了太多的屏幕空間,以至於您想在它們之間放置評論,那么您可能有足夠的空間想要使用某種循環。


正如 Deathless 先生在評論中提到的那樣,PyPI 上有一個名為contextlib2 contextlib反向移植 如果您使用的是 Python 2,則可以使用ExitStack的 backport 實現。


順便說一句,你不能做這樣的事情的原因

with (
        ThingA() as a,
        ThingB() as b):
    ...

是因為 a (也可以是上下文管理器的表達式的第一個標記,並且 CPython 的當前解析器在看到第一個(時無法判斷它應該解析什么規則。這是一個激勵示例對於PEP 617 ,它引入了一個更強大的新解析器,因此您想要的語法可能很快就會出現。

這對我來說似乎最整潔:

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

僅限 Python 3.9+:

with (
    Dummy() as a,
    Dummy() as b,
    # my comment explaining why I wanted Dummy() as c
    Dummy() as c,
):
    pass

蟒≤3.8:

with \
    Dummy() as a, \
    Dummy() as b, \
    Dummy() as c:
    pass

不幸的是,這種語法無法進行注釋。


這是它有效的證據:

Python 3.9.0a6 (default, Jun 20 2020, 14:52:53) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.15.0 -- An enhanced Interactive Python. Type '?' for help.

In [3]: with (open('x') 
   ...:        as f): 
   ...:     pass 
   ...:                                                                                                                                                                                                 
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-3-47d5a51db08b> in <module>
----> 1 with (open('x')
      2        as f):
      3     pass
      4 

FileNotFoundError: [Errno 2] No such file or directory: 'x'

In [4]:                                                                                                                                                                                                 
Do you really want to exit ([y]/n)? y

wPython 3.8.2 (default, May  8 2020, 20:08:31) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.15.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: with (open('x') 
   ...:       as f): 
   ...:     pass                                                                                                                                                                                        
  File "<ipython-input-1-e538abd13934>", line 2
    as f):
    ^
SyntaxError: invalid syntax

這並不完全干凈,但你可以這樣做:

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 的錯誤 E124

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

IMO它仍然很丑,但至少它通過了短絨。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM