What is the equivalent try statement of the with statement in Python?

一曲冷凌霜 提交于 2019-12-24 04:26:03

问题


After reading the with statement section of the language documentation of Python, I was wondering if it is correct to state that this Python code:

with EXPRESSION as TARGET:
    SUITE

is equivalent to this one:

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)

Edit

The correct equivalent Python code (the real CPython implementation is in C) was actually given by Guido van Rossum himself in PEP 343:

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)

Since Python 3.6, this has changed a little: now the __enter__ function is loaded before the __exit__ function (cf. https://bugs.python.org/issue27100).

So my equivalent Python code had three flaws:

  1. The __enter__ and __exit__ functions should be loaded before calling the __enter__ function.
  2. The __enter__ function should be called outside the try statement (cf. the note of point 4 in the language documentation).
  3. The else clause should instead be a finally clause, to handle the case when there is a non-local goto statement (break, continue, return) in suite.

However I don’t understand why the equivalent Python code in PEP 343 puts the finally clause in an outer try statement instead of in the inner try statement?


回答1:


Nick Coghlan, the other author of PEP 343, answered on the Python bug tracker:

It's a matter of historical timing: PEP 343 was written before try/except/finally was allowed, when try/finally and try/except were still distinct statements.

However, PEP 341 was also accepted and implemented for Python 2.5, allowing for the modern try/except/finally form: https://docs.python.org/dev/whatsnew/2.5.html#pep-341-unified-try-except-finally

So the modern try statement equivalent Python code of the with statement is this one:

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)


来源:https://stackoverflow.com/questions/59322585/what-is-the-equivalent-try-statement-of-the-with-statement-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!