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

学习python或者其他有异常控制的编程语 言, 大家很有可能说try except finally(try catch finally)的执行很简单,无非就是有异常的话执行except, finally无论是否有异常都会执行, 大致上原则是这样, 但是如果涉及到更加详细的复杂的路径,加上return 语句,就没有那么简单了。

1. 没有return 语句的情况

  1. print 'this is a test of code path in try...except...else...finally'
  2. print '************************************************************'
  3.  
  4. def exceptTest():
  5. try:
  6. print 'doing some work, and maybe exception will be raised'
  7. raise IndexError('index error')
  8. #print 'after exception raise'
  9. #return 0
  10.  
  11. except KeyError, e:
  12. print 'in KeyError except'
  13. print e
  14. #return 1
  15. except IndexError, e:
  16. print 'in IndexError except'
  17. print e
  18. #return 2
  19. except ZeroDivisionError, e:
  20. print 'in ZeroDivisionError'
  21. print e
  22. #return 3
  23. else:
  24. print 'no exception'
  25. #return 4
  26. finally:
  27. print 'in finally'
  28. #return 5
  29.  
  30. resultCode = exceptTest()
  31. print resultCode
上面的代码是一直要使用的代码,只不过暂时不用的代码被comment了。

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

  1. this is a test of code path in try...except...else...finally
  2. ************************************************************
  3. doing some work, and maybe exception will be raised
  4. in IndexError except
  5. index error
  6. in finally
  7. None

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

2. 添加return 语句的情况

  1. print 'this is a test of code path in try...except...else...finally'
  2. print '************************************************************'
  3.  
  4. def exceptTest():
  5. try:
  6. print 'doing some work, and maybe exception will be raised'
  7. raise IndexError('index error')
  8. print 'after exception raise'
  9. return 0
  10.  
  11. except KeyError, e:
  12. print 'in KeyError except'
  13. print e
  14. return 1
  15. except IndexError, e:
  16. print 'in IndexError except'
  17. print e
  18. return 2
  19. except ZeroDivisionError, e:
  20. print 'in ZeroDivisionError'
  21. print e
  22. return 3
  23. else:
  24. print 'no exception'
  25. return 4
  26. finally:
  27. print 'in finally'
  28. return 5
  29.  
  30. resultCode = exceptTest()
  31. print resultCode

这个时候所有的分支都存在return 语句,并且会引发异常, 看一下输出:

  1. this is a test of code path in try...except...else...finally
  2. ************************************************************
  3. doing some work, and maybe exception will be raised
  4. in IndexError except
  5. index error
  6. in finally
  7. 5

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

然后,我们在看看把finally 的返回值注释掉,看看返回值是多少?

代码如下:

  1. print 'this is a test of code path in try...except...else...finally'
  2. print '************************************************************'
  3.  
  4. def exceptTest():
  5. try:
  6. print 'doing some work, and maybe exception will be raised'
  7. raise IndexError('index error')
  8. print 'after exception raise'
  9. return 0
  10.  
  11. except KeyError, e:
  12. print 'in KeyError except'
  13. print e
  14. return 1
  15. except IndexError, e:
  16. print 'in IndexError except'
  17. print e
  18. return 2
  19. except ZeroDivisionError, e:
  20. print 'in ZeroDivisionError'
  21. print e
  22. return 3
  23. else:
  24. print 'no exception'
  25. return 4
  26. finally:
  27. print 'in finally'
  28. #return 5
  29.  
  30. resultCode = exceptTest()
  31. print resultCode

这个时候的程序输出:

  1. this is a test of code path in try...except...else...finally
  2. ************************************************************
  3. doing some work, and maybe exception will be raised
  4. in IndexError except
  5. index error
  6. in finally
  7. 2

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

3. 没有异常发生且try语句块没有return

代码如下:

  1. print 'this is a test of code path in try...except...else...finally'
  2. print '************************************************************'
  3.  
  4. def exceptTest():
  5. try:
  6. print 'doing some work, and maybe exception will be raised'
  7. #raise IndexError('index error')
  8. print 'after exception raise'
  9. #return 0
  10.  
  11. except KeyError, e:
  12. print 'in KeyError except'
  13. print e
  14. return 1
  15. except IndexError, e:
  16. print 'in IndexError except'
  17. print e
  18. return 2
  19. except ZeroDivisionError, e:
  20. print 'in ZeroDivisionError'
  21. print e
  22. return 3
  23. else:
  24. print 'no exception'
  25. return 4
  26. finally:
  27. print 'in finally'
  28. return 5
  29.  
  30. resultCode = exceptTest()
  31. print resultCode

这个时候的代码输出:

  1. this is a test of code path in try...except...else...finally
  2. ************************************************************
  3. doing some work, and maybe exception will be raised
  4. after exception raise
  5. no exception
  6. in finally
  7. 5

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

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

4. 没有异常发生且try语句块 存在return语句

  1. print 'this is a test of code path in try...except...else...finally'
  2. print '************************************************************'
  3.  
  4. def exceptTest():
  5. try:
  6. print 'doing some work, and maybe exception will be raised'
  7. #raise IndexError('index error')
  8. print 'after exception raise'
  9. return 0
  10.  
  11. except KeyError, e:
  12. print 'in KeyError except'
  13. print e
  14. return 1
  15. except IndexError, e:
  16. print 'in IndexError except'
  17. print e
  18. return 2
  19. except ZeroDivisionError, e:
  20. print 'in ZeroDivisionError'
  21. print e
  22. return 3
  23. else:
  24. print 'no exception'
  25. return 4
  26. finally:
  27. print 'in finally'
  28. return 5
  29.  
  30. resultCode = exceptTest()
  31. print resultCode

执行结果:

  1. this is a test of code path in try...except...else...finally
  2. ************************************************************
  3. doing some work, and maybe exception will be raised
  4. after exception raise
  5. in finally
  6. 5

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

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

5. 有异常发生并且finally 没有return 语句

  1. print 'this is a test of code path in try...except...else...finally'
  2. print '************************************************************'
  3.  
  4. def exceptTest():
  5. try:
  6. print 'doing some work, and maybe exception will be raised'
  7. raise IndexError('index error')
  8. print 'after exception raise'
  9. return 0
  10.  
  11. except KeyError, e:
  12. print 'in KeyError except'
  13. print e
  14. return 1
  15. except IndexError, e:
  16. print 'in IndexError except'
  17. print e
  18. return 2
  19. except ZeroDivisionError, e:
  20. print 'in ZeroDivisionError'
  21. print e
  22. return 3
  23. else:
  24. print 'no exception'
  25. return 4
  26. finally:
  27. print 'in finally'
  28. #return 5
  29.  
  30. resultCode = exceptTest()
  31. print resultCode

执行结果:

  1. this is a test of code path in try...except...else...finally
  2. ************************************************************
  3. doing some work, and maybe exception will be raised
  4. in IndexError except
  5. index error
  6. in finally
  7. 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

Python异常捕捉try except else finally有return时执行顺序探究的更多相关文章

  1. python 异常捕捉与异常处理

    简介 在实际开发中,为了防止异常界面直接被用户看到,往往我们会采用捕捉异常的方式来进一步处理异常. 异常捕捉 如下代码由于下标越界会导致异常 data = range(10) print(data[1 ...

  2. python 异常捕捉总结

    Process finished with exit code -1 错误 执行代码 pycharm2020.1中手动中断程序,可是却捕捉不了中断异常,并且输出Process finished wit ...

  3. python异常捕捉以及处理

    看标题觉得高大上,好像能处理所有的异常.但是,事实是只能按照字面的意思来理解这一段话. 众所周知写代码哪有不出bug的? 那么出现了bug 我们不想让程序因为bug的存在而退出.那么要怎么做呢? 今天 ...

  4. Python异常捕捉的一个小问题

    问题: names = ['taotao','songwenjing','liu','li']I = iter(names)while True: try: s = next(I) except Ex ...

  5. python nose测试框架全面介绍十二 ----用例执行顺序打乱

    在实际执行自动化测试时,发现我们的用例在使用同一个资源的操作时,用例的执行顺序对测试结果有影响,在手工测试时是完全没法覆盖的. 但每一次都是按用例名字来执行,怎么打乱来执行的. 在网上看到一个有意思的 ...

  6. python单元测试框架-unittest(三)之用例执行顺序

    执行顺序规则: 测试类或测试方法的数字与字母顺序0~9,A-Z 执行如下脚本,理解用例执行顺序 #coding=utf-8 import unittest class Test1(unittest.T ...

  7. python nose 自写插件打乱class类中用例执行顺序,但将test_a和test_z排除

    在使用nose时,有这样一个需求,用例执行打乱,但部分用例因场景原因必须先执行,这类用例在写用例时人为的加上了test_a或test_z字样 网上找了一圈,都没找到合适的方法,只有自己写插件了 已写完 ...

  8. python 异常

    引用一段来自菜鸟教程的文章:http://www.runoob.com/python/python-exceptions.html Python 异常处理 python提供了两个非常重要的功能来处理p ...

  9. #21 Python异常

    前言 运行程序时经常遇到各种错误,例如:ImportError(导入模块错误).IndexError(索引错误).NameError(变量错误).SyntaxError(语法错误).Indentati ...

随机推荐

  1. QT学习记录

    QApplication app(argc,argv); 创建了一个QApplication对象,这个对象用于管理应用程序级别的资源.QApplication的构造函数要求两个参数,分别来自main的 ...

  2. 第201天:js---实现继承的5种方式

    一.构造函数方式 //构造函数 function People(){ this.race = '汉族'; } People.prototype={ eat:function(){ console.lo ...

  3. SDOI2017 解题报告

    数字表格 \(T\)次询问,每次给出\(n,m(n,m\le 10^6)\),\(f\)为斐波那契数列,\(f_0=0,f_1=1\),求: \[ \prod _{i=1}^n\prod _{j=1} ...

  4. C++解析(29):类型识别

    0.目录 1.类型识别 2.动态类型识别 3.类型识别关键字 4.小结 1.类型识别 在面向对象中可能出现下面的情况: 基类指针指向子类对象 基类引用成为子类对象的别名 静态类型--变量(对象)自身的 ...

  5. 最长上升子序列nlogn算法

    LIS问题是经典的动态规划问题,它的状态转移相信大家都很熟悉: f[i] = f[k] + 1  (k < i 且 A[k] < A[i]) 显然这样做复杂度是O(n^2) 有没有更快的算 ...

  6. python基础(5)

    使用dict和set dict Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. 举个例子 ...

  7. OpenCV C++如何使RGB图像变为灰度图像

    http://m.blog.csdn.net/blog/u014395105/41308979 最近在研究如何用C++来处理图像,而不使用封装好的OpenCV代码,这样能够更好的了解OpenCV的内部 ...

  8. python之numpy矩阵库的使用(续)

    本文是对我原先写的python常用序列list.tuples及矩阵库numpy的使用中的numpy矩阵库的使用的补充.结合我个人现在对线性代数的复习进度来不断更博. Section 1:行列式的计算 ...

  9. stout代码分析之一:Duration类

    Duration类用于表示时间长度,可精确到纳秒. 代码实现在duration.hpp中,测试代码:duration_tests.cpp 相关api如下: parse, 将字符串转化成Duration ...

  10. 12.UiAutomator 获取系统信息

    一.Build构建信息 1.build类: Build类提供了硬件厂商.编号.序列号.SDK版本等重要信息. 类名:android.os.Build 常量名 说明 BOARD 底层板名称 BOOTLO ...