finally
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返回。
随机推荐
- Linux之socket套接字编程20160704
介绍套接字之前,我们先看一下传输层的协议TCP与UDP: TCP协议与UDP协议的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UD ...
- Picture POJ - 1177 (线段树-扫描线)
A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...
- [mysql][【优化集合】mysql数据库优化集合
三个层面: 1.系统层面 2.mysql配置参数 3.sql语句优化 =========================================================== 一.系统层 ...
- Leetcode 485. 最大连续1的个数
1.题目描述(简单题) 给定一个二进制数组, 计算其中最大连续1的个数. 示例 1: 输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 ...
- A星寻路算法-Mind&Hand(C++)
//注1:Mind & Hand,MIT校训,这里指的理解与实现(动脑也动手) //注2:博文分为两部分:(1)理解部分,为参考其他优秀博文的摘要梳理:(2)代码部分,是C++代码实现的,源码 ...
- UVA 11922 Splay tree
UVA 11922 题意: 有n个数1~n 操作a,b表示取出第a~b个数,翻转后添加到数列的尾部 输入n,m 输入m条指令a,b 输出最终的序列 代码: #include<iostream&g ...
- HDU 4529 状压dp
郑厂长系列故事——N骑士问题 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)To ...
- Maven搭建SpringMVC + SpringJDBC项目详解
前言 上一次复习搭建了SpringMVC+Mybatis,这次搭建一下SpringMVC,采用的是SpringJDBC,没有采用任何其他的ORM框架,SpringMVC提供了一整套的WEB框架,所以如 ...
- Long Parameter List(过长参数列)---要重构的味道
一个函数,它的参数过多是不好的,不好维护和修改,易读性也差,容易出错. 消除过长参数的方法,有如下: 1.在面向对象中,你可以传递一个对象给函数,函数通过访问对象来获得参 ...
- 【HDU】2222 Keywords Search
[算法]AC自动机 [题解]本题注意题意是多少关键字能匹配而不是能匹配多少次,以及可能有重复单词. 询问时AC自动机与KMP最大的区别是因为建立了trie,所以对于目标串T与自动机串是否匹配只需要直接 ...