在 try.. 之后不是列出语句吗?除了做同样的事情吗?
不,不是。您假设您已经涵盖了该块可以退出的所有方式。
finally 保证被执行即使块被退出。这包括return、continue 或break,不仅是例外。
对于您的具体示例,您几乎覆盖了try 块之外的所有可能路径。但是你没有覆盖KeyboardInterrupt 或MemoryError。如果有人在执行过程中点击了CTRL-C,那么只有第一个示例才会执行print("some code at last") 行。
那是因为你的代码没有捕捉到KeyboardInterrupt 或MemoryError,但这些异常仍然可能发生。如果为result = 100 / 0 语句引发了其中一个异常,则不会捕获该异常并且将退出整个帧。但不是在finally: 子句执行之前。
用一个不同的例子来演示更容易,一个没有捕捉到异常的例子:
mapping = {42: "The answer"}
try:
result = mapping[42] / 17
except KeyError:
print("Oops, no key 42 defined!")
else:
print(result)
finally:
del mapping
这里,finally 语句将被执行,即使上面引发了 TypeError 异常:
>>> mapping = {42: "The answer"}
>>> try:
... result = mapping[42] / 17
... except KeyError:
... print("Oops, no key 42 defined!")
... else:
... print(result)
... finally:
... del mapping
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'int'
>>> mapping # was deleted in the `finally` block
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'mapping' is not defined
这就是finally 通常的用途,清理资源。你甚至可以在 return 退出函数时使用它:
>>> def foo():
... try:
... return 42
... finally:
... print("Returning doesn't stop finally from executing!")
... print("This is never reached")
...
>>> foo()
Returning doesn't stop finally from executing!
42
请注意,Python 也有 with statement 和 context managers 来帮助完成相同的工作。上下文管理器封装通常在 finally 中完成的清理工作,让您避免在较长的代码段末尾查找 finally 块来检查是否有文件已关闭。
所以而不是:
fileobj = open(filename)
try:
with line in fileobj:
# many lines of parsing code
# .
# etc.
# .
finally:
fileobj.close()
您可以将文件对象用作上下文管理器,以上内容简化为:
with open(filename) as fileobj:
with line in fileobj:
# many lines of parsing code
# .
# etc.
# .