带括号的上下文管理器在 python 3.9 中有效,但在 3.8 中无效

mog*_*goh 5 python with-statement contextmanager python-3.x python-3.9

所以我有一个简单的声明示例with。它适用于 Python 3.8 和 3.9:

class Foo:
    def __enter__(self, *args):
        print("enter")

    def __exit__(self, *args):
        print("exit")

with Foo() as f, Foo() as b:
    print("Foo")
Run Code Online (Sandbox Code Playgroud)

输出(如预期):

enter
enter
Foo
exit
exit
Run Code Online (Sandbox Code Playgroud)

但如果我像这样添加括号,它只适用于 Python 3.9:

class Foo:
    def __enter__(self, *args):
        print("enter")

    def __exit__(self, *args):
        print("exit")

with (Foo() as f, Foo() as b):
    print("Foo")
Run Code Online (Sandbox Code Playgroud)

3.8 中的输出:

  File "foo.py", line 8
    with (Foo() as f, Foo() as b):
                ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

我知道,我可以删除括号,但我不明白为什么它首先在 Python 3.9 中工作。我找不到相关的变更日志。

Tom*_*koo 7

带括号的上下文管理器在What\xe2\x80\x99s New In Python 3.10中被提及为新功能。变更日志指出:

\n
\n

此新语法使用新解析器的非 LL(1) 功能。检查\n PEP 617了解更多详细信息。

\n
\n

PEP 617已在 Python 3.9 中被接受,如其变更日志中所述:

\n
\n

Python 3.9 使用新的解析器,基于PEG而不是LL(1)。新的解析器 xe2x80x99s 的性能与旧解析器的性能大致相当,但在设计新的语言功能时,PEG 形式比 LL(1) 更灵活。我们\xe2\x80\x99将在Python 3.10及更高版本中开始使用这种灵活性。

\n
\n

它甚至已经成为Python 3.9 语法的一部分:

\n
\n
with_stmt:\n    | \'with\' \'(\' \',\'.with_item+ \',\'? \')\' \':\' block \n    | \'with\' \',\'.with_item+ \':\' [TYPE_COMMENT] block \n    | ASYNC \'with\' \'(\' \',\'.with_item+ \',\'? \')\' \':\' block \n    | ASYNC \'with\' \',\'.with_item+ \':\' [TYPE_COMMENT] block \nwith_item:\n    | expression \'as\' star_target &(\',\' | \')\' | \':\') \n    | expression\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我的猜测是,因为 LL1 解析器在 Python 3.10 中被正式删除,所以才被认为是一个新功能,同时在 3.9 中仍然受支持。

\n