finally

我们都知道无论try语句中是否抛出异常,finally中的语句一定会被执行。我们来看下面的例子:

try:
f = open("/tmp/output", "w")
f.write("hello")
#raise Exception("something wrong")
finally:
print("closing file")
f.close()

代码

不论try中写文件的过程中是否有异常,finally中关闭文件的操作一定会执行。由于finally的这个特性,finally经常被用来做一些清理工作。
我们再来看下面的例子

def func1():
try:
return
finally:
return def func2():
try:
raise ValueError()
except:
return
finally:
return print(func1())
print(func2())

例子

这个例子中 func1() 和 func2() 返回什么呢?

答案是 func1() 返回2, func2() 返回3。为什么是这样的呢?我们先来看一段Python官网上对于finally的解释:

A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. When an exception has occurred in the try clause and has not been handled by an except clause (or it has occurred in a except or else clause), it is re-raised after the finally clause has been executed. The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement.

重点部分用粗体标出了,翻成中文就是try块中包含break、continue或者return语句的,在离开try块之前,finally中的语句也会被执行。
所以在上面的例子中,func1() 中,在try块return之前,会执行finally中的语句,try中的return被忽略了,最终返回的值是finally中return的值。func2() 中,try块中抛出异常,被except捕获,在except块return之前,执行finally中的语句,except中的return被忽略,最终返回的值是finally中return的值。
我们在上面的例子中加入print语句,可以更清楚地看到过程

def func1():
try:
print 'in func1 try: try statement, will return 1'
return
finally:
print 'in func1 finally: try statement, will return 2'
return def func2():
try:
print 'in func2 try: raise error'
raise ValueError()
except:
print 'in func2 except: caught error, will return 1!'
return
finally:
print 'in func2 finally: will return 3'
return print func1()
print func2()

加print代码

上面的代码输出

in func1 try: try statement, will return
in func1 finally: try statement, will return in func2 try: raise error
in func2 except: caught error, will return !
in func2 finally: will return

结果

我们对上面的func2做一些修改,如下

def func2():
try:
print 'in func2 try: raise error'
raise ValueError()
except IndexError:
print 'in func2 except: caught error, will return 1!'
return
finally:
print 'in func2 finally: will return 3'
return print func2()

修改代码

输出如下

in func2 try: raise error
in func2 finally: will return

结果

try中抛出的异常是ValueError类型的,而except中定位的是IndexError类型的,try中抛出的异常没有被捕获到,所以except中的语句没有被执行,但不论异常有没有被捕获,finally还是会执行,最终函数返回了finally中的返回值3。

这里还可以看到另外一个问题。try中抛出的异常没有被捕获到,按理说当finally执行完毕后,应该被再次抛出,但finally里执行了return,导致异常被丢失。
可以看到在finally中使用return会导致很多问题。实际应用中,不推荐在finally中使用return返回。

最新文章

  1. hadoop集群安装故障解决
  2. 浅谈iOS版本号
  3. AchartEngine 的学习
  4. yii学习笔记
  5. InfluxDB安装
  6. "org.eclipse.wst.validation" has been removed
  7. laravel定时任务
  8. elasticsearch2.3.3安装
  9. UNIX环境高级编程——时间和日期
  10. jsonp实现ajax跨域
  11. 写入mssql出现乱码
  12. 中文数据解码报错 UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence
  13. log4j(五)——如何控制不同目的地的日志输出?
  14. create table repo_folder_operate_log_bak as select * from repo_folder_operate_log;
  15. Python20-Day06
  16. Redis学习(4)-数据类型,string,hash
  17. html5的canvas方法的总结
  18. C#冒泡排序法及优化
  19. NGUI EventDelagate事件委托
  20. node.js中express-session配置项详解

热门文章

  1. BZOJ5248:[九省联考2018]一双木棋——题解
  2. jsp电子商务购物车之五 数据库存储篇2
  3. TYVJ2032 升降梯上
  4. Eclipse的Project Facets属性设置解决项目无故报错
  5. How to speed up insertion performance in PostgreSQL
  6. bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心
  7. ACM.hdu1025
  8. springboot-为内置tomcat设置虚拟目录
  9. MSSQL,MySQL 语法区别
  10. Tomcat免安装版+Eclipse配置