学习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

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

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

    转载自 https://www.cnblogs.com/JohnABC/p/4065437.html 学习python或者其他有异常控制的编程语 言, 大家很有可能说try except finall ...

  2. 我敢说你不一定完全理解try 块,catch块,finally 块中return的执行顺序

    大家好,今天我们来讲一个笔试和面试偶尔都会问到的问题,并且在工作中不知道原理,也会造成滥用. 大家可能都知道,try 块用来捕获异常,catch块是处理try块捕获的异常,finally 块是用来关闭 ...

  3. Python面试题之多个装饰器执行顺序

    疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会说明它们是自上而下的,比如下面这个例子: def decorator_a(func): print 'Get in decorator_a' def ...

  4. return & finally 执行顺序 这是我读到的最合理的解释

    新词:return [expression]  栈顶元素 局部变量的快照 java方法是在栈幀中执行,栈幀是线程私有栈的单位,执行方法的线程会为每一个方法分配一小块栈空间来作为该方法执行时的内存空间, ...

  5. python中 try、except、finally 的执行顺序

        def test1(): try: print('to do stuff') raise Exception('hehe') print('to return in try') return ...

  6. JAVA中try、catch、finally带return的执行顺序总结

    异常处理中,try.catch.finally的执行顺序,大家都知道是按顺序执行的.即,如果try中没有异常,则顺序为try→finally,如果try中有异常,则顺序为try→catch→final ...

  7. 理清Java中try-catch-finally带return的执行顺序

    前言:try-catch-finally带return和异常时,它们之间执行顺序问题是留下来的一个小疑问,今天搞清楚它们 第一种情况:无异常 //1.try-catch-finally都带有retur ...

  8. java中的try-catch-finally中的return的执行顺序

    在这里看到了try catch finally块中含有return语句时程序执行的几种情况,但其实总结的并不全,而且分析的比较含糊.但有一点是可以肯定的,finally块中的内容会先于try中的ret ...

  9. python中 try、except、finally 的执行顺序(转)

    def test1(): try: print('to do stuff') raise Exception('hehe') print('to return in try') return 'try ...

随机推荐

  1. 在Mac系统上安装Tomcat

    到 apache官方主页 下载 Mac 版本的完整 .gz文件包.解压拷贝到 /Library目录下.   1.Mac中 Finder打开 Library的方法 新建 Finder窗口   按下 sh ...

  2. JavaFX学习之Web

    PopupFeatures 处理新窗口    WebHistory 网页一般都带有历史记录的功能,可以回退,也可以前进,fx用WebHistory处理. final WebHistory wh = w ...

  3. WM-G-MR-09模块

    WM-G-MR-09模块,该模块同时支持SDIO与SPI 模式 USI(环隆电气)WM-G-MR-09,该WiFi芯片支持802.11b/g无线网络模式,芯片体积8.2×8.4×1.35(mm),采用 ...

  4. c++多行字符串,可以这么写

    c++多行字符串,可以这么写:CString s;s.Format("CREATE TABLE %s(\[ID] [int] IDENTITY(1,1) NOT NULL,\[Vendor] ...

  5. 仿LOL项目开发第四天

    ---恢复内容开始--- 仿LOL项目开发第四天 by草帽 上节讲了几乎所有的更新版本的逻辑,那么这节课我们来补充界面框架的搭建的讲解. 我们知道游戏中的每个界面都有自己的一个类型:比如登陆界面,创建 ...

  6. jquery的功能函数

    1.$.boxModel <!DOCTYPE html> <html> <head> <script src="/jquery/jquery-1.1 ...

  7. DGN格式转化为shp格式 【转】

    其实本来,我就是需要把一个autocad的dwg/dgn格式的东西导入到google earth里面:但是首先我对dwg/dgn格式的东西根本就不熟:其次我拿到的dwg/dgn格式文件是用的HK80 ...

  8. 对开源库使用 AutoCAD 文件格式[转]

    https://www.ibm.com/developerworks/cn/opensource/os-autocad/ 对开源库使用 AutoCAD 文件格式 读取 DWG 和 DXF 文件格式 C ...

  9. ExtJS ComboBox 录入智能提示

    ExtJS ComboBox非常复杂,有很多的属性:其中有的属性是针对某一种特定的方案而设计的,不是所有情况下都有效.我想下拉选择能支持录入,并且录入时能智能提示,弄了半天可以了,但是只能是mode= ...

  10. windows安装Jupyter Notebook

    这是我自定义的Python 的安装目录 (D:\SoftWare\Python\Python36\Scripts) 1.Jupyter Notebook 和 pip 为了更加方便地写 Python 代 ...