使用Python實(shí)現(xiàn)with結(jié)構(gòu)的@contextmanager方法詳解
常見with結(jié)構(gòu)
常見的with結(jié)構(gòu)是在進(jìn)行文件操作時(shí),比如
# 中規(guī)中矩的寫法 f = open("test.txt", "w") f.write("hello world!") f.close() # 采用with結(jié)構(gòu) with open("test.txt", "w") as f: f.write("hello world!")
這個(gè)結(jié)構(gòu)的好處,一個(gè)是簡(jiǎn)潔,一個(gè)是當(dāng)我們對(duì)文件操作的邏輯很長(zhǎng)的時(shí)候,不會(huì)因?yàn)橥岁P(guān)閉文件而造成不必要的錯(cuò)誤。
類似的,當(dāng)我們?cè)谀承r(shí)候不希望遺忘一些重要的語句的時(shí)候,可以自己封裝個(gè)with結(jié)構(gòu),比如關(guān)閉數(shù)據(jù)庫(kù)鏈接等情況。
一般實(shí)現(xiàn)方法
with結(jié)構(gòu)一般的實(shí)現(xiàn)方法是在定義類的時(shí)候重載__enter__
方法和__exit__
方法
比如我們可以通過如下代碼來模擬一下上面兩段代碼前者到后者的轉(zhuǎn)化
# -*- coding: utf-8 -*- class myOpen(): def __init__(self, name, state): self.f = open(name, state) # 返回值是with...as...中as出來的東西,如下面的f def __enter__(self): return self.f # 在with...as...語句塊自動(dòng)執(zhí)行完之后執(zhí)行 def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() if __name__ == "__main__": with myOpen("test.txt", "w") as f: f.write("hello world!")
@contextmanager方法
好像上面這種方法實(shí)現(xiàn)起來with結(jié)構(gòu)有那么一點(diǎn)點(diǎn)麻煩,那么就進(jìn)入主題吧,有一種逼格又高,又簡(jiǎn)便的方法,先上代碼,仍以打開文件為例:
# -*- coding: utf-8 -*- from contextlib import contextmanager @contextmanager def myOpen(name, state): try: f = open(name, state) yield f finally: f.close() if __name__ == "__main__": with myOpen("test.txt", "w") as f: f.write("hello world!")
可以看出這里只要定義一個(gè)函數(shù),然后在它的頭部加上@contextmanager就好了
這個(gè)函數(shù)應(yīng)該怎么定義呢?我們?nèi)ピ创a里看一下就好,里面給出了詳細(xì)的注釋
def contextmanager(func): """@contextmanager decorator. Typical usage: @contextmanager def some_generator(<arguments>): <setup> try: yield <value> finally: <cleanup> This makes this: with some_generator(<arguments>) as <variable>: <body> equivalent to this: <setup> try: <variable> = <value> <body> finally: <cleanup> """ @wraps(func) def helper(*args, **kwds): return GeneratorContextManager(func(*args, **kwds)) return helper
通過注釋我們可以看到,我們可以通過給一個(gè)try…finally…結(jié)構(gòu)的函數(shù)頭部加上@contextmanager就可以通過with…as…結(jié)構(gòu)來調(diào)用它了
這樣try塊中yield的數(shù)據(jù)被as出來,finally塊中的數(shù)據(jù)在with..as..塊結(jié)束的時(shí)候被執(zhí)行。
到此這篇關(guān)于使用Python實(shí)現(xiàn)with結(jié)構(gòu)的@contextmanager方法詳解的文章就介紹到這了,更多相關(guān)Python實(shí)現(xiàn)with結(jié)構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pytorch+sklearn實(shí)現(xiàn)數(shù)據(jù)加載的流程
這篇文章主要介紹了pytorch+sklearn實(shí)現(xiàn)數(shù)據(jù)加載,之前在訓(xùn)練網(wǎng)絡(luò)的時(shí)候加載數(shù)據(jù)都是稀里糊涂的放進(jìn)去的,也沒有理清楚里面的流程,今天整理一下,加深理解,也方便以后查閱,需要的朋友可以參考下2022-11-11Python中的引用知識(shí)點(diǎn)總結(jié)
在本文里我們給大家整理了關(guān)于Python中的引用知識(shí)點(diǎn)以及相關(guān)代碼總結(jié),需要的朋友們跟著學(xué)習(xí)下。2019-05-05python數(shù)據(jù)庫(kù)PooledDB連接池初始化使用示例
這篇文章主要為大家介紹了python數(shù)據(jù)庫(kù)PooledDB連接池初始化使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08解決Python中定時(shí)任務(wù)線程無法自動(dòng)退出的問題
今天小編就為大家分享一篇解決Python中定時(shí)任務(wù)線程無法自動(dòng)退出的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-02-02python實(shí)現(xiàn)用戶管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)用戶管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01