Python菜鳥晉級05----with....as....(上下文管理器),
介紹
上下文管理器(context manager)是Python2.5開始支援的一種文法,用於規定某個對象的使用範圍。一旦進入或者離開該使用範圍,會有特殊操作被調用 (比如為對象分配或者釋放記憶體)。它的文法形式是with...as...
應用
比較一下兩段代碼:
沒有使用上下文管理器:
writer = open("test.txt", "w")try: writer.write('Hello ') writer.write('World')finally: writer.close()
使用上下文管理器:
with open("test.txt", "w") as writer: writer.write("Hello World!")上面兩段代碼作用相同,但是下面的代碼是不是比上面的代碼優雅多了?
open函數既能夠當做一個簡單的函數使用,又能夠作為上下文管理器。這是因為open函數返回了一個檔案類型變數,而這個檔案類型實現了我們之前用到的write方法,但是想要作為上下文管理器還必須實現一些特殊的方法,我會在接下來的小節中介紹。
自訂上下文管理器要實現上下文管理器,必須實現兩個方法——一個負責進入語句塊的準備操作(__enter__ 方法),另一個負責離開語句塊的善後操作(__exit__ 方法)。
當一個對象被用作上下文管理器時:
__enter__ 方法將在進入代碼塊前被調用。
__exit__ 方法則在離開代碼塊之後被調用(即使在代碼塊中遇到了異常)。
class Test: def __enter__(self): print("進入模組") def __exit__(self,*unused): print("離開模組")with Test(): #由於我不需要調用方法,因此我沒有使用as關鍵詞 print("模組中執行的語句")
輸出結果
>>> 進入模組模組中執行的語句離開模組>>>
自己實現的上下文管理器
class PypixOpen: def __init__(self, filename, mode): self.filename = filename self.mode = mode def __enter__(self): self.openedFile = open(self.filename, self.mode) return self.openedFile def __exit__(self, *unused): self.openedFile.close() with PypixOpen(filename, mode) as writer: writer.write("Hello World from our new Context Manager!")
值得注意的是:
我們完全忽視了語句塊內部可能出現的問題。
如果語句塊內部發生了異常,__exit__方法將被調用,而異常將會被重新拋出(re-raised)。當處理檔案寫入操作時,大部分時間你肯定不希望隱藏這些異常,所以這是可以的。而對於不希望重新拋出的異常,我們可以讓__exit__方法簡單的返回True來忽略語句塊中發生的所有異常(大部分情況下這都不是明智之舉)。
上面代碼*unused 指向exc_type, exc_value, traceback三個參數,當程式塊中出現異常(exception),這三個參數用於描述異常。我們可以根據這三個參數進行相應的處理。如果正常運行結束,這三個參數都是None。
上一講:Python菜鳥晉級04----raw_input() 與 input()的區別
下一講:
如果有什麼疑問歡迎到我的公眾號提問~