[英]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.