python 中 try...finally... 的優雅實現
阿新 • • 發佈:2020-11-25
### 1. 關於 try.. finally..
假如上帝用 python 為每一個來到世界的生物編寫程式,那麼除去中間過程的種種複雜實現,最不可避免的就是要保證每個例項最後都要掛掉。程式碼可簡寫如下:
```py
try:
born() # 出生
# 正常降臨世界
# do something..
except ValueError:
# 安排錯誤
# do something...
except AttributeError:
# 特徵錯誤
# do something...
except TypeError:
# 種類錯誤
# do something...
... # 等等雜七雜八的錯誤
finally:
go_die() # 掛掉
come_to_see_me() # 然後來見我
reincarnate() # 下一輪,安排!
```
這就是 `finally` 的作用和例項。就算捕獲異常後再次出現異常,最終也能保證 `go_die` 方法會執行,但是,如果 `go_die` 方法出現錯誤,那麼就不能正常去見上帝了。為了保證每個生物(不管有沒有掛掉)都能見到上帝他老人家,並開始下一個輪迴(不管有沒有見到),需要做如下處理:
```py
...
finally:
try:
go_die()
finally:
try:
come_to_see_me()
finally:
reincarnate()
```
OK,功能雖然實現了,但按照 `The Zen of Python` 所說:`Flat is better than nested.`(扁平優於巢狀),那麼這段程式碼就略顯醜陋了。為了遵循 python 美學,我們可以對這段進行優化,使它看起來更為美觀。
### 2. 錯誤的上下文:`__context__`
在此之前,需要引入一個新的概念: `__context__`,`__context__` 的字面意思就是上下文,它屬於錯誤的一個屬性。在錯誤捕獲中,它意味著當你處理一個錯誤時,另一個錯誤發生了。也就是說,你所捕獲的錯誤雖然被成功捕獲了,但當捕獲完成時,你的一些操作導致另一個錯誤發生,而這個錯誤並沒有被捕獲。通常情況下,如果處理的好,那麼**當前錯誤**的 `__context__` 的值為 `None`,如果處理不好那就是你所捕獲的錯誤。比如下面的程式碼:
```py
def type_err():
raise TypeError('this is a type error.')
def after_type_err():
raise ValueError('this is a value error.')
try:
type_err()
except TypeError:
after_type_err()
```
執行結果為:
```python
Traceback (most recent call last):