最終,上下文管理器可能幾乎與子程序(subroutine)自己同樣重要。python
在各類語言中 with 語句的做用不一樣,並且作的都是簡單的事,雖然能夠避免不
斷使用點號查找屬性,可是不會作事前準備和過後清理。編程
else太個性了, 其餘語言不一樣用 不用這個多線程
取得原諒比得到許可容易(easier to ask for forgiveness than permission)。這是一
種常見的 Python 編程風格,先假定存在有效的鍵或屬性,若是假定不成立,那麼捕
獲異常。這種風格簡單明快,特色是代碼中有不少 try 和 except 語句。與其餘不少
語言同樣(如 C 語言),這種風格的對立面是 LBYL 風格。
接下來,詞彙表定義了 LBYL。app
三思然後行(look before you leap)。這種編程風格在調用函數或查找屬性或鍵
以前顯式測試前提條件。與 EAFP 風格相反,這種風格的特色是代碼中有不少 if 語
句。在多線程環境中,LBYL 風格可能會在「檢查」和「行事」的空當引入條件競爭。例
如,對 if key in mapping: return mapping[key] 這段代碼來講,若是在測試
以後,但在查找以前,另外一個線程從映射中刪除了那個鍵,那麼這段代碼就會失敗。
這個問題可使用鎖或者 EAFP 風格解決。ide
上下文管理器協議包含 enter 和 exit 兩個方法。with 語句開始運行時,會在上下文管理器對象上調用 enter 方法。函數
with 語句運行結束後,會在上下文管理器對象上調用 exit 方法,以此扮演 finally 子句的角色。測試
class LookingGlass: def __enter__(self): import sys self.original_write = sys.stdout.write sys.stdout.write = self.reverse_write return 'JABBERWOCKY' def reverse_write(self, text): self.original_write(text[::-1]) def __exit__(self, exc_type, exc_value, traceback): import sys sys.stdout.write = self.original_write if exc_type is ZeroDivisionError: print('Please DO NOT divide by zero!') return True
❻ 若是一切正常,Python 調用 exit 方法時傳入的參數是 None, None, None;如
果拋出了異常,這三個參數是異常數據,以下所述。線程
解釋器調用 enter 方法時,除了隱式的 self 以外,不會傳入任何參數。傳給
exit 方法的三個參數列舉以下。code
exc_type
異常類(例如 ZeroDivisionError)。對象
exc_value
異常實例。有時會有參數傳給異常構造方法,例如錯誤消息,這些參數可使用exc_value.args 獲取。
traceback
traceback 對象。
能減小建立上下文管理器的樣板代碼量,由於不用編寫一個完整的類,定義 enter 和 exit 方法,
而只需實現有一個 yield 語句的生成器,生成想讓 enter 方法返回的值。
def __enter__(self): 通常返回 self本身
def __exit__(self, exc_type, exc_value, traceback):
exc_type
異常類(例如 ZeroDivisionError)。exc_value
異常實例。有時會有參數傳給異常構造方法,例如錯誤消息,這些參數可使用exc_value.args 獲取。traceback traceback 對象。