擅长:python、mysql、java
<p>根据引入了上下文管理器的<a href="https://www.python.org/dev/peps/pep-0343/#specification-the-with-statement" rel="nofollow noreferrer">PEP-343</a>,代码</p>
<pre><code>with obj() as o:
do_something()
</code></pre>
<p>相当于</p>
<pre><code>mgr = obj()
exit = type(mgr).__exit__
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
o = value
do_something()
except:
exc = False
if not exit(mgr, *sys.exc_info()):
raise
finally:
if exc:
exit(mgr, None, None, None)
</code></pre>
<p>注意事项:</p>
<ol>
<li>我们不写<code>o = type(mgr).__enter__(mgr)</code>,因为只有在<code>__enter__</code>没有引发异常时才定义名称<code>o</code>,这样我们就可以输入<code>try</code>语句。(有其他的方法来处理这个问题,但这就是我如何解释PEP-343的翻译。)</li>
<li><code>__exit__</code>可以在两个不同的地方调用。如果捕获到异常,我们会将有关该异常的信息传递给<code>__exit__</code>,这样可以防止调用代码在返回<code>True</code>时看到它。你知道吗</li>
<li><code>finally</code>块确保<code>__exit__</code>只被调用一次。也就是说,如果没有引发异常,我们希望调用它,但是如果第一个调用通过返回<code>True</code>吞并了一个异常或者引发了一个异常本身,我们就不想再次调用它。你知道吗</li>
</ol>