with 語(yǔ)句適用于對(duì)資源進(jìn)行訪問(wèn)的場(chǎng)合,確保不管使用過(guò)程中是否發(fā)生異常都會(huì)執(zhí)行必要的“清理”操作,釋放資源,比如文件使用后自動(dòng)關(guān)閉、線程中鎖的自動(dòng)獲取和釋放等。
淺顯得講就是使用with語(yǔ)句,會(huì)自動(dòng)幫我們?cè)谶\(yùn)行結(jié)束后進(jìn)行清理,注意即使中途拋出異常,一樣會(huì)進(jìn)行清理,有點(diǎn)像unitest中 teardown的意思
舉個(gè)最常見(jiàn)得例子:
####不使用with語(yǔ)句
f=open("my.log","r")
try:
lines=f.readlines()
except Exception as e:
raise e
finally:
f.close()
####使用with語(yǔ)句
with open("my.log","r") as f:
lines=f.readlines()
如果不適用with語(yǔ)句需要在我們不使用文件得時(shí)候手動(dòng)去關(guān)閉文件,而with則不用,會(huì)自動(dòng)幫我們處理,不管運(yùn)行成功或者失敗
通過(guò)例子我們可以大致看出來(lái)with語(yǔ)句得語(yǔ)法格式
with context_expression [as something]:
with-body
需要注意with語(yǔ)句操作得對(duì)象必須具有上下文管理器,也就是需要具有__ enter__方法,__ exit__方法
__enter __:入口方法,運(yùn)行在with-body之前
__exit __:退出清理方法,運(yùn)行在with-body之后
剛剛得例子雖然能說(shuō)明問(wèn)題,但是看得不夠直觀,我們來(lái)創(chuàng)建一個(gè)具有上下文管理器得對(duì)象
class my():
def __enter__(self):
print("i am enter")
def __exit__(self, exc_type, exc_val, exc_tb):
print("i am exit")
with my() as haha:
print("i am with body")
###輸出
i am enter
i am with body
i am exit
上面得例子可以看出所有得運(yùn)行過(guò)程,但是并沒(méi)有體現(xiàn)出在with body中出錯(cuò)后會(huì)運(yùn)行exit方法,來(lái)看下面得例子:
class my():
def __enter__(self):
print("i am enter")
def __exit__(self, exc_type, exc_val, exc_tb):
print("i am exit")
with my() as haha:
print("i am with body"+1)
###輸出
i am enter
Traceback (most recent call last):
File "/Users/hjc/workspace/myutils/meiyouyong.py", line 8, in <module>
i am exit
print("i am with body"+1)
TypeError: must be str, not int
i am exit
可以看到exit方法被執(zhí)行了,但是這里有個(gè)bug,如果我們給my類加個(gè)成員方法,這時(shí)haha找不到該方法
class my():
def __enter__(self):
print("i am enter")
def __exit__(self, exc_type, exc_val, exc_tb):
print("i am exit")
def run(self):
print("i am run")
with my() as haha:
haha.run()
###運(yùn)行結(jié)果
i am enter
Traceback (most recent call last):
File "/Users/hjc/workspace/myutils/meiyouyong.py", line 10, in <module>
haha.run()
AttributeError: 'NoneType' object has no attribute 'run'
i am exit
上面得例子很明顯haha并沒(méi)有run方法,這是為什么呢,我們?cè)倏匆幌孪旅娴美?/p>
class my():
def __enter__(self):
print("i am enter")
def __exit__(self, exc_type, exc_val, exc_tb):
print("i am exit")
def run(self):
print("i am run")
with my() as haha:
my().run()
###運(yùn)行結(jié)果
i am enter
i am run
i am exit
我們把haha改成了my()就可以了,為什么haha作為my()得替代沒(méi)有呢,原因是my()先運(yùn)行得是enter方法,而enter并沒(méi)有返回值,導(dǎo)致haha替代my()時(shí)為None,自然沒(méi)有run()方法
class my():
def __enter__(self):
print("i am enter")
def __exit__(self, exc_type, exc_val, exc_tb):
print("i am exit")
def run(self):
print("i am run")
with my() as haha:
print(haha)
###運(yùn)行結(jié)果
i am enter
None
i am exit
找到問(wèn)題得原因就簡(jiǎn)單了,我們只要運(yùn)行enter時(shí)候把對(duì)象返回就好了
class my():
def __enter__(self):
print("i am enter")
return self #將對(duì)象返回
def __exit__(self, exc_type, exc_val, exc_tb):
print("i am exit")
def run(self):
print("i am run")
with my() as haha:
haha.run()
###運(yùn)行結(jié)果
i am enter
i am run
i am exit
ok,到這里就結(jié)束了