前言
with表達(dá)式其實(shí)是try-finally的簡寫形式。但是又不是全相同。
格式
"""
格式
with context [as var]:
pass
"""
其中的context是一個(gè)表達(dá)式,返回的是一個(gè)對(duì)象,var用來保存context表達(dá)式返回的對(duì)象,可以有單個(gè)或者多個(gè)返回值。
with open('1.txt') as f:
print(f.read())
print(f.closed)
表達(dá)式open('1.txt')返回是一個(gè)_io.TextIOWrapper 類型的變量用f接受到。在with語句塊中就可以使用這個(gè)變量操作文件。執(zhí)行with這個(gè)結(jié)構(gòu)之后。f會(huì)自動(dòng)關(guān)閉。相當(dāng)于自帶了一個(gè)finally。

image.png
但是with本身并沒有異常捕獲的功能,但是如果發(fā)生了運(yùn)行時(shí)異常,它照樣可以關(guān)閉文件釋放資源。
這個(gè)例子可以看出with沒有捕獲異常的功能。
with open('2.txt') as f:
print(f.read())
print(f.closed)

image.png
這個(gè)例子可以看出with發(fā)生了異常也會(huì)關(guān)閉程序。
try:
with open('1.txt') as f2:
print(f2.read())
f2.seek(-5,os.SEEK_SET)
except ValueError as e:
print("error")
print(f2.closed)

image.png
原理
"""
with 語句實(shí)質(zhì)是上下文管理。
1、上下文管理協(xié)議。包含方法__enter__() 和 __exit__(),支持該協(xié)議對(duì)象要實(shí)現(xiàn)這兩個(gè)方法。
2、上下文管理器,定義執(zhí)行with語句時(shí)要建立的運(yùn)行時(shí)上下文,負(fù)責(zé)執(zhí)行with語句塊上下文中的進(jìn)入與退出操作。
3、進(jìn)入上下文的時(shí)候執(zhí)行__enter__方法,如果設(shè)置as var語句,var變量接受__enter__()方法返回值。
4、如果運(yùn)行時(shí)發(fā)生了異常,就退出上下文管理器。調(diào)用管理器__exit__方法。
"""
自定義類
自定義類必須包含上述幾個(gè)方法才能正確使用with關(guān)鍵字。
class Mycontex(object):
def __init__(self,name):
self.name=name
def __enter__(self):
print("進(jìn)入enter")
return self
def do_self(self):
print(self.name)
def __exit__(self,exc_type,exc_value,traceback):
print("退出exit")
print(exc_type,exc_value)
if __name__ == '__main__':
with Mycontex('test') as mc:
mc.do_self()

image.png
下面我們故意加一個(gè)NameError

image.png
即使程序發(fā)生了錯(cuò)誤,python解釋器終止了我們的程序,但是我們的類 還是順利關(guān)閉了。
應(yīng)用場景
1、文件操作。2、進(jìn)程線程之間互斥對(duì)象。3、支持上下文其他對(duì)象