在Python的异常处理中,基本的结构是如下:
>>> try:
pass
except:
pass
finally:
pass
思路是:
1)先执行try语句块;
2)如果try语句块发生异常,且与except中的异常相同,则执行except语句块;
3)无论是否有异常,最后执行finally语句块。
但是如果在每个语句块中加入return语句,那么执行顺序是如何的呢?
下面看几个列子:
1、不带return语句的情况
print('this is a test of code path in try...except...else...finally')
print('************************************************************')
def exceptTest():
try:
print('doing some work, and maybe exception will be raised')
raise IndexError('index error')
print('after exception raise')
# return 0
except IndexError as e:
print('in IndexError except')
print(e)
# return 1
else:
print('no exception')
# return 2
finally:
print('in finally')
# return 3
resultCode = exceptTest()
print(resultCode)
上面的代码中,将所有return的语句注释掉,执行结果如下:
this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
None
2、添加return语句(try语句块中产生异常,匹配到except语句块,跳过else语句块,最后执行finally语句块)
print('this is a test of code path in try...except...else...finally')
print('************************************************************')
def exceptTest():
try:
print('doing some work, and maybe exception will be raised')
raise IndexError('index error')
print('after exception raise')
return 0
except IndexError as e:
print('in IndexError except')
print(e)
return 1
else:
print('no exception')
return 2
finally:
print('in finally')
return 3
resultCode = exceptTest()
print(resultCode)
输出结果为:(finally语句块中的return语句拥有最高优先级输出)
this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
3
3、只有finally语句中不添加return语句(try语句块中产生异常,匹配到except语句块,跳过else语句块,最后执行finally语句块):
print('this is a test of code path in try...except...else...finally')
print('************************************************************')
def exceptTest():
try:
print('doing some work, and maybe exception will be raised')
raise IndexError('index error')
print('after exception raise')
return 0
except IndexError as e:
print('in IndexError except')
print(e)
return 1
else:
print('no exception')
return 2
finally:
print('in finally')
# return 3
resultCode = exceptTest()
print(resultCode)
输入结果为:
this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
1
此时返回值变为1。
因为有异常发生,try语句中的return没有执行到,然后到捕捉到的except语句块中执行,并且except语句块中存在return语句,而finally语句时必须要执行的,所有except里的return语句先搁置,然后finally执行完后返回到except语句块中执行return,因此最终的返回值为1。
4、finally中不添加return,且try语句块中不产生异常:
print('this is a test of code path in try...except...else...finally')
print('************************************************************')
def exceptTest():
try:
print('doing some work, and maybe exception will be raised')
# raise IndexError('index error')
print('after exception raise')
return 0
except IndexError as e:
print('in IndexError except')
print(e)
return 1
else:
print('no exception')
return 2
finally:
print('in finally')
# return 3
resultCode = exceptTest()
print(resultCode)
执行结果如下:
this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
after exception raise
in finally
0
这里可以看到没有返回else的return值,因为没有异常发生,会执行到try语句块中的return语句,而finally语句块必须执行,所有这里的return语句也搁置,先执行完finally语句块,然后返回到try语句块中的return语句,而try语句块执行了return语句,所以else语句块并没有得到执行。
结论:
1)如果没有异常发生, try中有return 语句, 这个时候else块中的代码是没有办法执行到的, 但是finally语句中如果有return 语句会修改最终的返回值, 我个人理解的是try中return 语句先将要返回的值放在某个 CPU寄存器,然后运行finally语句的时候修改了这个寄存器的值,最后在返回到try中的return语句返回修改后的值。
2.)如果没有异常发生, try中没有return语句,那么else块的代码是执行的,但是如果else中有return, 那么也要先执行finally的代码, 返回值的修改与上面一条一致。
3.)如果有异常发生,try中的return语句肯定是执行不到, 在捕获异常的 except语句中,如果存在return语句,那么也要先执行finally的代码,finally里面的代码会修改最终的返回值,然后在从 except 块的retrun 语句返回最终修改的返回值, 和第一条一致。