Python学习之路(18)——try except else finally语句块有return时的执行顺序探究

在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 语句返回最终修改的返回值, 和第一条一致。

posted on 2018-03-03 20:59  nicolas_Z  阅读(508)  评论(1)    收藏  举报

导航