【问题标题】:What is the equivalent try statement of the with statement?with 语句的等效 try 语句是什么?
【发布时间】:2019-12-13 12:26:22
【问题描述】:

在阅读了Python语言文档的with statement section之后,我想知道是否声明这段Python代码是正确的:

with EXPRESSION as TARGET:
    SUITE

相当于这个:

try:
    manager = (EXPRESSION)
    value = manager.__enter__()
    TARGET = value  # only if `as TARGET` is present in the with statement
    SUITE
except:
    import sys
    if not manager.__exit__(*sys.exc_info()):
        raise
else:
    manager.__exit__(None, None, None)

编辑

Guido van Rossum 本人在PEP 343 中实际上给出了正确的等效 Python 代码(真正的 CPython 实现在 C 中):

mgr = (EXPR)
exit = type(mgr).__exit__  # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
    try:
        VAR = value  # Only if "as VAR" is present
        BLOCK
    except:
        # The exceptional case is handled here
        exc = False
        if not exit(mgr, *sys.exc_info()):
            raise
        # The exception is swallowed if exit() returns true
finally:
    # The normal and non-local-goto cases are handled here
    if exc:
        exit(mgr, None, None, None)

自 Python 3.6 以来,这发生了一些变化:现在 __enter__ 函数在__exit__ 函数之前加载(参见https://bugs.python.org/issue27100)。

所以我的等效 Python 代码存在三个缺陷:

  1. 应在调用__enter__ 函数之前加载__enter____exit__ 函数。
  2. __enter__ 函数应在 try 语句之外调用(参见语言文档中第 4 点的注释)。
  3. else 子句应改为finally 子句,以处理suite 中存在非本地goto 语句(breakcontinuereturn)的情况。李>

但是我不明白为什么 PEP 343 中的等效 Python 代码将 finally 子句放在外部 try 语句而不是内部 try 语句中?

【问题讨论】:

标签: python try-catch with-statement


【解决方案1】:

PEP 343 的另一位作者 Nick Coghlan 在Python bug tracker 上回答:

这是历史时间问题:PEP 343 是在之前编写的 当 try/finally 和 try/except 被允许时,try/except/finally 被允许 仍然是不同的陈述。

然而,PEP 341被 Python 2.5 接受并实现, 允许现代的 try/except/finally 形式: https://docs.python.org/dev/whatsnew/2.5.html#pep-341-unified-try-except-finally

因此,with 语句的现代 try 语句等效 Python 代码是这样的:

manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False

try:
    TARGET = value  # only if `as TARGET` is present in the with statement
    SUITE
except:
    import sys
    hit_except = True
    if not exit(manager, *sys.exc_info()):
        raise
finally:
    if not hit_except:
        exit(manager, None, None, None)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 2018-02-24
  • 2011-09-23
  • 2021-02-17
相关资源
最近更新 更多