Python with語句和過程抽取思想
python中的with語句使用于對(duì)資源進(jìn)行訪問的場(chǎng)合,保證不管處理過程中是否發(fā)生錯(cuò)誤或者異常都會(huì)執(zhí)行規(guī)定的__exit__(“清理”)操作,釋放被訪問的資源,比如有文件讀寫后自動(dòng)關(guān)閉、線程中鎖的自動(dòng)獲取和釋放等。
與python中with語句有關(guān)的概念有:上下文管理協(xié)議、上下文管理器、運(yùn)行時(shí)上下文、上下文表達(dá)式、處理資源的代碼段。
with語句的應(yīng)用場(chǎng)景
編程中有很多操作都是配套使用的,這種配套的流程可以稱為計(jì)算過程,Python語言為這種計(jì)算過程專門設(shè)計(jì)了一種結(jié)構(gòu):with語句。比如文件處理就是這類計(jì)算過程的典型代表。
使用with語句前后對(duì)比
沒有使用with語句之前,我們是這樣打開一個(gè)文件的:
try: # 1. [進(jìn)入] f = open('a.txt', 'r', encoding="utf-8") # 2. [執(zhí)行] print(f.read()) finally: if f: # 3. [退出] f.close()
python操作文件的流程一般就是這三步:
1.[進(jìn)入]用只讀方式打開文件
如果文件不存在,open()函數(shù)就會(huì)拋出一個(gè)IOError的錯(cuò)誤,并且給出錯(cuò)誤碼和詳細(xì)的信息告訴你文件不存在
2.[執(zhí)行]讀取文件內(nèi)容
如果文件打開成功,接下來,調(diào)用read()方法可以一次讀取文件的全部?jī)?nèi)容,Python把內(nèi)容讀到內(nèi)存,用一個(gè)str對(duì)象表示
3.[退出]關(guān)閉打開的文件
文件使用完畢后必須關(guān)閉,因?yàn)槲募?duì)象會(huì)占用操作系統(tǒng)的資源,并且操作系統(tǒng)同一時(shí)間能打開的文件數(shù)量也是有限的
思考為什么關(guān)閉文件操作一定要放在finallly語句里?
由于文件讀寫時(shí)都有可能產(chǎn)生IOError,一旦出錯(cuò),后面的f.close()就不會(huì)調(diào)用。所以,為了保證無論是否出錯(cuò)都能正確地關(guān)閉文件,我們可以使用try ... finally來實(shí)現(xiàn)。
發(fā)現(xiàn)共性:
我們發(fā)現(xiàn)其實(shí)這種過程化的語句有共性,比如說在進(jìn)去一個(gè)片段前
必須做某種超贊,處理工作后
又需要執(zhí)行一個(gè)結(jié)束操作。比如上面的這段代碼:
finally: if f: f.close()
就可以做一個(gè)封裝。
使用with語句后,我們是這樣打開一個(gè)文件的:
with open("a.txt", "r", encoding="utf-8") as f: print(f.read())
這個(gè)with語句和前面的try ... finally結(jié)構(gòu)是一樣的,但是代碼更佳簡(jiǎn)潔,并且不必調(diào)用f.close()方法。
with語句的執(zhí)行原理
從解釋器的角度去理解with語句執(zhí)行流程。
with語句的基本形式是:
with 表達(dá)式 as 變量: 語句塊
這樣的一段代碼可以稱為一個(gè)上下文(context),在執(zhí)行with語句時(shí),解釋器會(huì)先求出表達(dá)式的值,這個(gè)值(對(duì)象)是一個(gè)上下文管理器,并且假設(shè)這個(gè)對(duì)象擁有如下類的構(gòu)造方法:
def __enter__(): # 描述進(jìn)入上下文的動(dòng)作 pass def __exit__(): # 描述退出上下文的動(dòng)作 pass
with語句在求出這個(gè)上下文管理器對(duì)象之后,自動(dòng)執(zhí)行進(jìn)入方法
,并將這個(gè)對(duì)象的返回值賦值于 as 之后的變量,然后執(zhí)行語句塊。然后在退出上下文前,自動(dòng)執(zhí)行對(duì)象的退出方法
。
python系統(tǒng)和標(biāo)準(zhǔn)庫(kù)的一些類型定義了這對(duì)操作,可以直接用于with語句。比如文件對(duì)象就直接支持這一對(duì)操作,因此可以用在with語句的頭部。
如果你也有類似的計(jì)算過程需要抽取出來,那么可以自定義一個(gè)類,并且包含進(jìn)入、退出方法。
自定義open函數(shù)
自己實(shí)現(xiàn)才發(fā)現(xiàn),使用裝飾器和生成器就能很好的解決這個(gè)問題,不需要用到類構(gòu)造方法來實(shí)現(xiàn);
import contextlib # 引入上下文管理包 @contextlib.contextmanager # 給函數(shù)引入裝飾器 def myopen(dir, mode): print("開始") f = open(dir, mode, encoding='utf-8') try: # 上文 yield f finally: # 下文 print("結(jié)束") f.close() with myopen("a.txt", 'r') as fobj: # 把try中的yield中的f賦值給fobj # with會(huì)將with后面的函數(shù)中的yield賦值給fobj for i in fobj: print(i) # 等待上面的循環(huán)結(jié)束后,才最終執(zhí)行finally的代碼,所以這就是上下文管理
輸出:
開始 hello,我是a.txt的第1行文字。 結(jié)束
總結(jié)
打開文件讀寫、用pickle包完成數(shù)據(jù)的存儲(chǔ)、恢復(fù)的操作,都非常適合使用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.")
我總結(jié)了一下使用with語句的優(yōu)點(diǎn):
- 采用with語句的代碼更簡(jiǎn)潔
- 防止因?yàn)橥泴慺.close()而引發(fā)的錯(cuò)誤
- 一個(gè)對(duì)象的操作有進(jìn)入、退出過程可以抽取出來,并做成自動(dòng)化執(zhí)行
總結(jié)
以上所述是小編給大家介紹的Python with語句和過程抽取思想,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
pytorch使用Variable實(shí)現(xiàn)線性回歸
這篇文章主要為大家詳細(xì)介紹了pytorch使用Variable實(shí)現(xiàn)線性回歸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05python實(shí)現(xiàn)MySQL指定表增量同步數(shù)據(jù)到clickhouse的腳本
這篇文章主要介紹了python實(shí)現(xiàn)MySQL指定表增量同步數(shù)據(jù)到clickhouse的腳本,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Python原始字符串(raw strings)用法實(shí)例
這篇文章主要介紹了Python原始字符串(raw strings)用法實(shí)例,在使用Python進(jìn)行字符串處理的過程中非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10Python爬蟲爬取愛奇藝電影片庫(kù)首頁的實(shí)例代碼
這篇文章主要介紹了Python爬蟲爬取愛奇藝電影片庫(kù)首頁的實(shí)例代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05Python?jpg快速轉(zhuǎn)png并調(diào)整大小方式
這篇文章主要介紹了Python實(shí)現(xiàn)jpg快速轉(zhuǎn)png并調(diào)整大小方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03python中內(nèi)置函數(shù)ord()返回字符串的ASCII數(shù)值實(shí)例詳解
ord()?函數(shù)是?chr()?函數(shù)(對(duì)于?8?位的?ASCII?字符串)的配對(duì)函數(shù),它以一個(gè)字符串(Unicode?字符)作為參數(shù),返回對(duì)應(yīng)的?ASCII?數(shù)值,或者?Unicode?數(shù)值,這篇文章主要介紹了python?中內(nèi)置函數(shù)ord()返回字符串的ASCII數(shù)值,需要的朋友可以參考下2022-07-07Python3 常用數(shù)據(jù)標(biāo)準(zhǔn)化方法詳解
這篇文章主要介紹了Python3 常用數(shù)據(jù)標(biāo)準(zhǔn)化方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03Python實(shí)現(xiàn)的基于優(yōu)先等級(jí)分配糖果問題算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的基于優(yōu)先等級(jí)分配糖果問題算法,涉及Python針對(duì)列表的遍歷、判斷、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下2018-04-04