你在 Python 中常常寫的 with..as.. 到底是個啥?
with 語句可以說是 Python 中 “人生苦短,我用 Python” 的經(jīng)典代表之一,它可以使得我們在編寫代碼的時候非常簡短,且行之有效。
舉一個簡單的例子,在 Java 中,你想要讀取一個文件中的內(nèi)容,一般來說需要自己定義一個這樣的讀取方法:

而在 Python 中,想要讀取文件就可以直接這樣:

這樣看起來,是挺短呀。

其實文件操作中所涉及到的 try...except..finally 都給封裝起來了:

而我們通過 with 拿了對象就可以直接操作了,是不是有點強大,那么它是怎么做到的呢?
接下來就是:學(xué)習(xí) python 的正確姿勢

with 語句是用于上下文對象的管理,通過它你就可以操作上下文對象:

比如上面這個,在 with 調(diào)用后得到的 Handsomeb對象里面,需要用到 __enter__ () 和 __exit__() 這兩個方法,也就是說,如果你想要讓你創(chuàng)建的對象能被 with 使用,那么你這個對象必須要有 __enter__ () 和 __exit__() 這兩個方法。
這兩個方法是干什么用的呢?
當我們使用 with 去執(zhí)行這個對象的時候,就會先去調(diào)用 ?__enter__ () ?,最后再調(diào)用 __exit__() :

打印出來是這樣的:

可以看到,我們使用 with 去調(diào)用 get_Handsomeb ,得到的這個對象會先執(zhí)行“進入 enter 方法”,接著再執(zhí)行 with 里面的 “get...”,等都執(zhí)行完畢之后,再去執(zhí)行 “進入 exit 方法” 。
我們再來看看 with..后面緊跟著的 as 是干嘛的呢?

在這里的 as 后面的變量名稱,其實得到的就是 enter 方法返回的值。

你看,我在 enter 方法中定義返回了 “handsomeb” ,然后使用 “with .. as h” 的方式獲取對象, 從打印結(jié)果可以看到:這時候 h 得到的就是 enter 方法中的返回值?“handsomeb” 。
可以返回一個對象:

接著,我們再來看看我們定義的這個 ?__exit__ 方法,細心點你會發(fā)現(xiàn),這里攜帶了這么幾個參數(shù):type, value, trace。
它們是干嘛的呢?這就是我們開頭所說的問題。
我們在操作一些對象的時候,比如操作文件的時候,可能會發(fā)現(xiàn)這樣那樣未知的異常,比如文件的位置找不到了,文件打不開了等等問題,關(guān)于這些異常的信息,我們可以在 __exit__ 方法中得到。
舉個例子:
我們將type,?value,?trace這幾個參數(shù)都打印出來,然后創(chuàng)建一個計算的方法:

不過這個方法執(zhí)行的是 100/0 ,我們知道 0 是不能作為除數(shù)的,這樣是會報錯的,我們使用 with 來調(diào)用下看看:

執(zhí)行結(jié)果是這樣的:

可以看到,這些拋出的異常信息,我們可以在 exit 方法中的參數(shù)中直接獲取,那么就可以在這里做一些事情(對一些異常進行處理)了,比如說,在文件操作中,我們到最后都需要關(guān)閉這個文件流的,但是有了 exit 這個方法, Python 直接在里面做了資源關(guān)閉操作,我們就不需要再手動去關(guān)閉了。
ok,以上就是今天我給你分享的 with 工作方式,總結(jié)一下就是:
1.通過 with 語句可以得到一個上下文管理器
2.執(zhí)行對象
3.加載?__enter__ 方法
4.加載?__exit__ 方法
5.執(zhí)行 __enter__
6.as?可以得到 enter?的返回值
7.拿到對象執(zhí)行相關(guān)操作
8.執(zhí)行完了之后調(diào)用?__exit__ 方法
9.如果遇到異常,__exit__ 可以獲取到異常信息
10.在 __exit__ 中處理異常,返回 True
11.繼續(xù)執(zhí)行 with 后面的語句。
希望對你有幫助,我們下回見,peace!
