Python中“try”语句的可选“else”子句的预期用途是什么?
在try
语句中,可选的else
部分是用来做什么的呢?
22 个回答
Python中的try-else
try语句中的可选
else
部分的用途是什么呢?
它的主要目的是在没有出现预期中的错误时,提供一个地方让更多的代码运行。
这样可以避免意外处理那些你没有预料到的错误。
不过,理解导致else部分运行的具体条件是很重要的,因为return
、continue
和break
会打断控制流,导致不执行else
。
总结一下
只有在没有出现任何异常,并且没有被return
、continue
或break
打断的情况下,else
语句才会执行。
其他回答忽略了最后这一点。
可选的
else
部分在控制流“流出”try
部分的末尾时执行。
(加粗部分是强调的。) 脚注中写道:
*目前,控制流“流出末尾”除非出现异常,或者执行了
return
、continue
或break
语句。
它确实需要至少有一个前面的except部分(见语法)。所以它其实不是“try-else”,而是“try-except-else(-finally)”,其中else
(和finally
)是可选的。
Python教程详细说明了它的用途:
try ... except语句有一个可选的else部分,当它存在时,必须跟在所有except部分之后。它适用于在try部分没有引发异常时必须执行的代码。例如:
for arg in sys.argv[1:]: try: f = open(arg, 'r') except OSError: print('cannot open', arg) else: print(arg, 'has', len(f.readlines()), 'lines') f.close()
使用else部分比在try部分添加额外代码要好,因为它可以避免意外捕获那些没有被try ... except语句保护的代码引发的异常。
示例:区分else
与try块后面的代码
如果你处理了一个错误,else
块将不会执行。例如:
def handle_error():
try:
raise RuntimeError('oops!')
except RuntimeError as error:
print('handled a RuntimeError, no big deal.')
else:
print('if this prints, we had no error!') # won't print!
print('And now we have left the try block!') # will print!
现在,
>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!
使用 else
的一个重要原因是风格和可读性。通常,把可能引发错误的代码放在处理这些错误的代码附近是个好主意。比如,看看这两个例子:
try:
from EasyDialogs import AskPassword
# 20 other lines
getpass = AskPassword
except ImportError:
getpass = default_getpass
和
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
else:
# 20 other lines
getpass = AskPassword
第二个例子在 except
不能提前返回或者重新抛出错误时是比较好的。如果可以的话,我会这样写:
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
return False # or throw Exception('something more descriptive')
# 20 other lines
getpass = AskPassword
注意:这个回答是从最近发布的重复问题中复制过来的,详细内容可以在 这里找到,所以里面提到的“AskPassword”相关内容也是如此。
在try
块的代码执行完后,如果没有出现任何错误,else
块里的代码就会被执行。老实说,我自己用到这个的机会不多。
不过,处理异常中提到:
使用
else
子句比在try
块中添加额外的代码要好,因为这样可以避免意外捕获到不是由try ... except
保护的代码引发的异常。
所以,如果你有一个方法可能会抛出IOError
,你想捕获它引发的异常,但如果第一个操作成功后你还想做其他事情,并且你不想捕获那个操作中的IOError
,你可以这样写:
try:
operation_that_can_throw_ioerror()
except IOError:
handle_the_exception_somehow()
else:
# we don't want to catch the IOError if it's raised
another_operation_that_can_throw_ioerror()
finally:
something_we_always_need_to_do()
如果你只是把another_operation_that_can_throw_ioerror()
放在operation_that_can_throw_ioerror
后面,except
会捕获第二个调用的错误。如果你把它放在整个try
块的后面,它会一直被执行,直到finally
之后才会执行。使用else
可以确保:
- 第二个操作只有在没有异常时才会执行,
- 它在
finally
块之前执行, - 它引发的任何
IOError
不会在这里被捕获。