前言
with表達式其實是try-finally的簡寫形式。但是又不是全相同。
格式
"""
格式
with context [as var]:
pass
"""
其中的context是一個表達式桑腮,返回的是一個對象洽损,var用來保存context表達式返回的對象,可以有單個或者多個返回值张抄。
with open('1.txt') as f:
print(f.read())
print(f.closed)
表達式open('1.txt')返回是一個_io.TextIOWrapper 類型的變量用f接受到砂蔽。在with語句塊中就可以使用這個變量操作文件。執(zhí)行with這個結(jié)構之后署惯。f會自動關閉左驾。相當于自帶了一個finally。
但是with本身并沒有異常捕獲的功能极谊,但是如果發(fā)生了運行時異常诡右,它照樣可以關閉文件釋放資源。
這個例子可以看出with沒有捕獲異常的功能轻猖。
with open('2.txt') as f:
print(f.read())
print(f.closed)
這個例子可以看出with發(fā)生了異常也會關閉程序帆吻。
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)
原理
"""
with 語句實質(zhì)是上下文管理。
1咙边、上下文管理協(xié)議猜煮。包含方法__enter__() 和 __exit__(),支持該協(xié)議對象要實現(xiàn)這兩個方法败许。
2友瘤、上下文管理器,定義執(zhí)行with語句時要建立的運行時上下文檐束,負責執(zhí)行with語句塊上下文中的進入與退出操作辫秧。
3、進入上下文的時候執(zhí)行__enter__方法被丧,如果設置as var語句盟戏,var變量接受__enter__()方法返回值。
4甥桂、如果運行時發(fā)生了異常柿究,就退出上下文管理器。調(diào)用管理器__exit__方法黄选。
"""
自定義類
自定義類必須包含上述幾個方法才能正確使用with關鍵字蝇摸。
class Mycontex(object):
def __init__(self,name):
self.name=name
def __enter__(self):
print("進入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()
下面我們故意加一個NameError
即使程序發(fā)生了錯誤婶肩,python解釋器終止了我們的程序,但是我們的類 還是順利關閉了貌夕。
應用場景
1律歼、文件操作。2啡专、進程線程之間互斥對象险毁。3、支持上下文其他對象