在學習python的過程中,經常會用到with
語句,比如在進行檔案操作時,會使用下面這樣的語法:
with
open
("1.txt"
,"r"
)as f:
print
(f.read(
))
這裡就會產生乙個疑問:f是不是就是open()函式的返回值呢?
其實並不是,這裡涉及到上下文管理器方面的知識,先來解釋一下什麼是上下文管理器物件吧。
我們都知道,python屬於鴨子型別的語言,只要乙個類實現了__getitem__()
方法或者__iter__()
方法,那個這個類的物件就是可迭代的。同樣,如果乙個類實現了__enter__()
和__exit__()
方法,那麼這個類的物件就是上下文管理器物件。
當with語句開始執行時,會獲取上下文管理器物件,上面的例子中open()函式返回的就是乙個實現了__enter__()
和__exit__()
方法的上下文管理器物件。接著會執行上下文管理器物件的__enter__()方法,如果這個方法有返回值,就會將這個返回值繫結在as
後面定義的物件上面。
這裡我們通過自定義乙個上下文管理器物件來驗證一下:
class
mycontextmanager
:def
__enter__
(self)
:print
("進入__enter__方法"
)return
"hello"
def__exit__
(self, exc_type, exc_value, traceback)
:return
true
上面我們自己定義了乙個實現__enter__()方法和__exit__()方法的上下文管理器類,接著我們使用with
語句來測試一下這個類:
with mycontextmanager(
)as f:
print
(f)
看一下輸出:
從結果我們可以看到,f確實是__enter__()方法的返回值。so,一定不要認為f是with後面語句的返回值,它是上下文管理器物件進入__enter__()方法後的返回值!
那麼在__exit__()方法為什麼會接受那麼多的引數呢?還有為什麼要返回true呢?
我們在使用with句法的時候,難免會在其中寫一些錯誤的**,比如1/0
這種,當with語句遇到這種異常,就會進入上下文管理器物件的__exit__()方法,同時將異常類,異常值和traceback傳遞給該方法,如果該方法返回none或者true,就代表上下文管理器物件處理了該異常,執行**時就不會報錯,如果返回的不是none或true,異常就會向上丟擲。
下面來用**測試一下:
class
mycontextmanager
:def
__enter__
(self)
:print
("進入__enter__方法"
)return
"hello"
def__exit__
(self, exc_type, exc_value, traceback)
:if exc_type is
notnone
:print
("出現了異常"
)return
true
if __name__ ==
'__main__'
:with mycontextmanager(
)as f:
print
(f)1
/0
在__exit__()方法中,我們首先判斷是否出現了異常,如果有異常發生,就輸出一句話,同時返回true,告訴with語句上下文管理器物件已經處理了這個異常。
輸出結果如下,可以看到輸出結果中並沒有異常發生:
如果我們在__exit__()方法中返回其它值會是什麼結果呢?來看看執行結果:
可以看到如果__exit__()方法在發生異常時返回空字串的話,with語句一旦出現異常,就會向上丟擲。
所以__exit__()方法的作用就在於可以讓使用者定義哪些異常需要向上丟擲,哪些不需要。
今天的上下文管理器物件就介紹到這裡啦!有時間可以去看看《fluent python》的第十五章對於上下文管理器物件的詳細介紹吧!
Python之上下文管理器
以下文章總結自 head first python 讀書筆記 從python處理乙個檔案說起,在python中開啟乙個檔案時,一般的 邏輯如下 file open test.txt for line in file print line file.close 以上 主要做了3件事 1 開啟乙個檔案 ...
python 之 上下文管理器
首先說一下什麼叫上下文管理器 在python中任何實現了 enter 和 exit 方法的物件都可稱之為上下文管理器,上下文管理器物件可以使用 with 關鍵字 我們可以模擬實現乙個類,讓該類實現 enter 和 exit 方法 class file def init self,filename,m...
python之上下文管理器 with語句詳解
上下文管理器 一 基本語法with expr as var pass 以最常用的with為例 操作文字物件的時候,幾乎所有的人都會讓我們要用with open,這就是乙個上下文管理器的一種。比如 with open 1.txt as f print f.readllines 輸出結果 print t...