來源:強(qiáng)哥 公眾號:Python與數(shù)據(jù)分析 鏈接: https://mp.weixin.qq.com/s/6jBvyl1YoVBRyVQCdC67Sg
無論try語句中是否拋出異常,finally中的語句一定會(huì)被執(zhí)行。我們來看下面的例子: try: f = open('/tmp/output', 'w') f.write('hello') #raise Exception('something wrong') finally: print('closing file') f.close()
不論try中寫文件的過程中是否有異常,finally中關(guān)閉文件的操作一定會(huì)執(zhí)行。由于finally的這個(gè)特性,finally經(jīng)常被用來做一些清理工作。
我們再來看下面的例子 def func1(): try: return 1 finally: return 2
def func2(): try: raise ValueError() except: return 1 finally: return 3
print(func1()) print(func2())
這個(gè)例子中 func1() 和 func2() 返回什么呢? 答案是 func1() 返回2, func2() 返回3。為什么是這樣的呢?我們先來看一段Python官網(wǎng)上對于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.
重點(diǎn)部分用粗體標(biāo)出了,翻成中文就是try塊中包含break、continue或者return語句的,在離開try塊之前,finally中的語句也會(huì)被執(zhí)行。 所以在上面的例子中,func1() 中,在try塊return之前,會(huì)執(zhí)行finally中的語句,try中的return被忽略了,最終返回的值是finally中return的值。func2() 中,try塊中拋出異常,被except捕獲,在except塊return之前,執(zhí)行finally中的語句,except中的return被忽略,最終返回的值是finally中return的值。 我們在上面的例子中加入print語句,可以更清楚地看到過程 def func1(): try: print 'in func1 try: try statement, will return 1' return 1 finally: print 'in func1 finally: try statement, will return 2' return 2
def func2(): try: print 'in func2 try: raise error' raise ValueError() except: print 'in func2 except: caught error, will return 1!' return 1 finally: print 'in func2 finally: will return 3' return 3
print func1() print func2()
上面的代碼輸出 in func1 try: try statement, will return 1 in func1 finally: try statement, will return 2 2 in func2 try: raise error in func2 except: caught error, will return 1! in func2 finally: will return 3 3
我們對上面的func2做一些修改,如下 def func2(): try: print 'in func2 try: raise error' raise ValueError() except IndexError: print 'in func2 except: caught error, will return 1!' return 1 finally: print 'in func2 finally: will return 3' return 3
print func2()
輸出如下 in func2 try: raise error in func2 finally: will return 3 3
try中拋出的異常是ValueError類型的,而except中定位的是IndexError類型的,try中拋出的異常沒有被捕獲到,所以except中的語句沒有被執(zhí)行,但不論異常有沒有被捕獲,finally還是會(huì)執(zhí)行,最終函數(shù)返回了finally中的返回值3。
這里還可以看到另外一個(gè)問題。try中拋出的異常沒有被捕獲到,按理說當(dāng)finally執(zhí)行完畢后,應(yīng)該被再次拋出,但finally里執(zhí)行了return,導(dǎo)致異常被丟失。 可以看到在finally中使用return會(huì)導(dǎo)致很多問題。實(shí)際應(yīng)用中,不推薦在finally中使用return返回。
(完)
看完本文有收獲?請轉(zhuǎn)發(fā)分享給更多人 關(guān)注「Python那些事」,做全棧開發(fā)工程師
|