Python 多行 with 语句

标签 python python-3.x multiline with-statement

在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 语句?

最佳答案

As of Python 3.10 ,现在可以将整个上下文管理器组括起来,就像您最初尝试的那样:

with (Dummy() as a, Dummy() as b,
      # comment about c
      Dummy() as c):
    pass

这在 3.9 中在技术上也是可行的,但处于一种半文档化的边缘。

一方面,它在 3.10 中被记录为新功能,3.9 不不应该引入任何依赖于 new parser implementation 的功能(例如这个) ,以及 3.9 with docs禁止这种形式。另一方面,该功能最终在 3.9 CPython 实现中被激活,并且(大部分?)自动生成的 3.9 full grammar spec包括括号内的表格。


在以前的 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 先生在评论中提到的,有一个 contextlib backport在名称为 contextlib2 的 PyPI 上。如果您使用的是 Python 2,则可以使用 backport 的 ExitStack 实现。


顺便说一句,你不能这样做的原因

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

在新的解析器实现之前是因为 ( 也可以是上下文管理器表达式的第一个标记,而 CPython 的旧解析器将无法判断它应该是什么规则当它看到第一个 ( 时进行解析。这是 PEP 617 的新的基于 PEG 的解析器的激励示例之一。

关于Python 多行 with 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31039022/

相关文章:

javascript - 正则表达式在多行文本中下一个匹配的开头处停止

Python Regex MULTILINE 选项无法正常工作?

python - 如何将属性添加到字典列表到Python中的列表理解?

python - 如何解析 Python3 BeautifulSoup 中的 onclick() 文本?

python - 如何在python中水平翻转mp4视频?

Python 3.6 Split() 没有足够的值来解压解决方法?

javascript - 如何更新多行字形的 ColumnDataSource 数据?

Python - AWS Lambda 从 JSON 输入中提取 key

python - pandas 排序值以获得 groupby 中每一列的前 5 名

python - numpy - 对整个矩阵的运算