Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 555|回复: 0

Python异常捕捉try except else finally有return时执行顺序探究

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-1 20:04:07 | 显示全部楼层 |阅读模式

    转载自 https://www.cnblogs.com/JohnABC/p/4065437.html

    学习python或者其他有异常控制的编程语 言, 大家很有可能说try except finally(try catch finally)的执行很简单,无非就是有异常的话执行except, 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 KeyError, e:
            print 'in KeyError except'
            print e
            #return 1
        except IndexError, e:
            print 'in IndexError except'
            print e
            #return 2
        except ZeroDivisionError, e:
            print 'in ZeroDivisionError'
            print e
            #return 3
        else:
            print 'no exception'
            #return 4
        finally:
            print 'in finally'
            #return 5
     
    resultCode = exceptTest()
    print resultCode
    复制代码
    上面的代码是一直要使用的代码,只不过暂时不用的代码被comment了。

    有异常发生,并且捕获异常,最后在finally进行处理,上面代码的输出:

    复制代码
    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
    复制代码

    然后我们逐渐给上面代码各个情况添加return 语句, 查看添加return 语句后的代码执行效果。

    2. 添加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 KeyError, e:
            print 'in KeyError except'
            print e
            return 1
        except IndexError, e:
            print 'in IndexError except'
            print e
            return 2
        except ZeroDivisionError, e:
            print 'in ZeroDivisionError'
            print e
            return 3
        else:
            print 'no exception'
            return 4
        finally:
            print 'in finally'
            return 5
     
    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
    5
    复制代码

    异常发生后,raise语句以后的不再执行,然后到了捕获异常语句, 但是捕获异常模块有个return , 是不是这个时候就不再继续执行直接返回呢?但是这是跟 finally语句必然执行是相冲突的, 可以在结果中看到finally实际上执行了,并且返回值是5,在 finally de 的返回值。

    然后,我们在看看把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 KeyError, e:
            print 'in KeyError except'
            print e
            return 1
        except IndexError, e:
            print 'in IndexError except'
            print e
            return 2
        except ZeroDivisionError, e:
            print 'in ZeroDivisionError'
            print e
            return 3
        else:
            print 'no exception'
            return 4
        finally:
            print 'in finally'
            #return 5
     
    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
    2
    复制代码

    返回值变为2, 这个时候有点疑惑了, 先不用解释问题,我们继续看其他的情况。

    3. 没有异常发生且try语句块没有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 KeyError, e:
            print 'in KeyError except'
            print e
            return 1
        except IndexError, e:
            print 'in IndexError except'
            print e
            return 2
        except ZeroDivisionError, e:
            print 'in ZeroDivisionError'
            print e
            return 3
        else:
            print 'no exception'
            return 4
        finally:
            print 'in finally'
            return 5
     
    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
    no exception
    in finally
    5
    复制代码

    这里验证了如果没有异常那么else语句是执行的,并且finally语句执行,然后返回finally语句的return 5

    但是,当try语句块里存在return语句是什么情况呢?

    4. 没有异常发生且try语句块 存在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 KeyError, e:
            print 'in KeyError except'
            print e
            return 1
        except IndexError, e:
            print 'in IndexError except'
            print e
            return 2
        except ZeroDivisionError, e:
            print 'in ZeroDivisionError'
            print e
            return 3
        else:
            print 'no exception'
            return 4
        finally:
            print 'in finally'
            return 5
     
    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
    5
    复制代码

    这里else没有执行,和我们对于书本知识有冲突了, finally语句执行并返回5.

    分析: 这里因为没有发生异常, 所以会执行到try块中的return 语句,但是finally又必须执行,所以执行try中return 之前去执行了finally语句,并且可以认为,finally语句修改了最后返回的值,将try中的返回值修改为5并最终返回,所以else语句并没有 得到执行。

    5. 有异常发生并且finally 没有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 KeyError, e:
            print 'in KeyError except'
            print e
            return 1
        except IndexError, e:
            print 'in IndexError except'
            print e
            return 2
        except ZeroDivisionError, e:
            print 'in ZeroDivisionError'
            print e
            return 3
        else:
            print 'no exception'
            return 4
        finally:
            print 'in finally'
            #return 5
     
    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
    2
    复制代码

    因为有异常发生,所以try中的return语句肯定是执行不到的,然后在捕获到的except中进行执行,并且except中存在return 语句,那么是不是就直接返回? 因为finally 语句是必须要执行的,所以这里的return语句需要先暂且放下,进入finally进行执行,然后finnaly执行完以后再返回到 except中进行执行。

    看到这里,我们貌似找到了一些规律

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

    转自:http://www.2cto.com/kf/201405/304975.html

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 22:39 , Processed in 0.059707 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表