返回介绍

建议25:避免 finally 中可能发生的陷阱

发布于 2024-01-30 22:19:09 字数 1511 浏览 0 评论 0 收藏 0

无论try语句中是否有异常抛出,finally语句总会被执行。由于这个特性,finally语句经常被用来做一些清理工作,如打开一个文件,抛出异常后在finally语句中对文件句柄进行关闭等。

但使用finally时,也要特别小心一些陷阱。先来看以下例子:

def FinallyTest():  
    print 'i am starting------'  
    while  True:  
        try:
          print "I am running"
          raise IndexError("r")#
抛出异IndexError
异常
        except NameError,e:  
          print 'NameError happended %s',e  
          break  
        finally:  
          print 'finally executed'
          break #finally
语句中有break
语句
FinallyTest()

上述程序输出结果为:

i am starting------
I am running
finally executed

上面的例子中try代码块抛出了IndexError异常,但在except块却没有对应的异常声明。按常理该异常会向上层抛出,可是程序输出却没有提示任何异常发生,IndexError异常被丢失。这是什么原因呢?当try块中发生异常的时候,如果在except语句中找不到对应的异常处理,异常将会被临时保存起来,当finally执行完毕的时候,临时保存的异常将会再次被抛出,但如果finally语句中产生了新的异常或者执行了return或者break语句,那么临时保存的异常将会被丢失,从而导致异常屏蔽。这是finally使用时需要小心的第一个陷阱。再来看另外一个例子:

def ReturnTest(a):
  try:
    if a <=0:
      raise ValueError("data can not be negative")
    else:
      return a
  except ValueError as e:
    print e
  finally:
  print("The End!")
  return -1
print ReturnTest(0)
print ReturnTest(2)

思考一下这里程序ReturnTest(0)和ReturnTest(2)的返回值是什么?答案是:-1,-1。对于第一个调用ReturnTest(0)在抛出ValueError异常后直接执行finally语句返回值为-1,这点比较容易理解;那么对于第二个调用ReturnTest(2)为什么也返回-1呢?这是因为a>0,会执行else分支,但由于存在finally语句,在执行else语句的return a语句之前会先执行finally中的语句,此时由于finally语句中有return -1,程序直接返回了,所以永远不会返回a对应的值2。此为使用finally语句需要注意的第二个陷阱。在实际应用程序开发过程中,并不推荐在finally中使用return语句进行返回,这种处理方式不仅会带来误解而且可能会引起非常严重的错误。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文