編程中有不少操做都是配套使用的,這種配套的流程能夠稱爲計算過程,Python語言爲這種計算過程專門設計了一種結構:with語句。好比文件處理就是這類計算過程的典型表明。python
沒有使用with語句以前,咱們是這樣打開一個文件的:編程
try: # 1. [進入] f = open('a.txt', 'r', encoding="utf-8") # 2. [執行] print(f.read()) finally: if f: # 3. [退出] f.close()
python操做文件的流程通常就是這三步:函數
思考爲何關閉文件操做必定要放在finallly語句裏?
因爲文件讀寫時都有可能產生IOError,一旦出錯,後面的f.close()就不會調用。因此,爲了保證不管是否出錯都能正確地關閉文件,咱們可使用try ... finally來實現。操作系統
發現共性:
咱們發現其實這種過程化的語句有共性,好比說在進去一個片斷前
必須作某種超讚,處理工做後
又須要執行一個結束操做。好比上面的這段代碼:設計
finally: if f: f.close()
就能夠作一個封裝。code
使用with語句後,咱們是這樣打開一個文件的:對象
with open("a.txt", "r", encoding="utf-8") as f: print(f.read())
這個with語句和前面的try ... finally結構是同樣的,可是代碼更佳簡潔,而且沒必要調用f.close()方法。內存
從解釋器的角度去理解with語句執行流程。utf-8
with語句的基本形式是:資源
with 表達式 as 變量: 語句塊
這樣的一段代碼能夠稱爲一個上下文(context),在執行with語句時,解釋器會先求出表達式的值,這個值(對象)是一個上下文管理器,而且這個對象擁有以下類構造方法:
def __enter__(): # 描述進入上下文的動做 pass def __exit__(): # 描述退出上下文的動做 pass
with語句在求出這個上下文管理器對象以後,自動執行進入方法
,並將這個對象的返回值賦值於 as 以後的變量,而後執行語句塊。而後在退出上下文前,自動執行對象的退出方法
。
python系統和標準庫的一些類型定義了這對操做,能夠直接用於with語句。好比文件對象就直接支持這一對操做,所以能夠用在with語句的頭部。
若是你也有相似的計算過程須要抽取出來,那麼能夠自定義一個類,而且包含進入、退出方法。
打開文件讀寫、用pickle包完成數據的存儲、恢復的操做,都很是適合使用with語句。
pickle包的使用案例:
try: with open("phone.pickle", "wb") as outf: pickle.dump("13193388105", outf) except: print("file have errow.") try: with open("phone.pickle", "rb") as outf: data = pickle.load(outf) print(type(data)) print(data) except: print("file have errow.")
我總結了兩個使用with語句的優勢:
採用with語句的代碼更簡潔
防止由於忘記寫f.close()而引起的錯誤
一個對象的操做有進入、退出過程能夠抽取出來,並作成自動化執行
《從問題到程序用Python編程和計算》