它的原理以下:
全部實現上下文協議的對象都包含如下三種方法:
__context__() 它返回一個自我管理的上下文對象,或者一個真正意義的上下文管理器
__enter()__ 進入上下文管理器,開始迭代
當with語句結束的時候,不管是正常結束仍是拋出異常,都會執行__exit__(),該方法用於關閉資源鏈接。 python
若是有一個類包含 __enter__ 方法和 __exit__ 方法,像這樣:
class controlled_execution:
def__enter__(self):
set things up
return thing
def__exit__(self, type, value, traceback): sql
tear things down
那麼它就能夠和with一塊兒使用,像這樣:
with controlled_execution() as thing:
some code
當with語句被執行的時候,python對錶達式進行求值,對求值的結果(叫作「內容守護者」)調用__enter__方法,並把__enter__方法的返回值賦給as後面的變量。而後python會執行接下來的代碼段,而且不管這段代碼幹了什麼,都會執行「內容守護者」的__exit__方法。
做爲額外的紅利,__exit__方法還可以在有exception的時候看到exception,而且壓制它或者對它作出必要的反應。要壓制exception,只須要返回一個true。好比,下面的__exit__方法吞掉了任何的TypeError,可是讓全部其餘的exceptions經過:
def__exit__(self, type, value, traceback):
return isinstance(value, TypeError)
在Python2.5中,file object擁有__enter__和__exit__方法,前者僅僅是返回object本身,然後者則關閉這個文件:
>>> f = open("x.txt")
>>> f
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.__enter__()
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.read(1)
'X'
>>> f.__exit__(None, None, None)
>>> f.read(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file
這樣要打開一個文件,處理它的內容,而且保證關閉它,你就能夠簡簡單單地這樣作:
with open("x.txt") as f:
data = f.read()
do something with data
個人補充:
數據庫的鏈接好像也能夠和with一塊兒使用,我在一本書上看到如下內容:
conn = sqlite.connect("somedb")
with conn:
conn.execute("insert into sometable values (?,?)",("foo","bar"))
在這個例子中,commit()是在全部with數據塊中的語句執行完畢而且沒有錯誤以後自動執行的,若是出現任何的異常,將執行rollback()操做,再次提示異常 數據庫