使用Python實(shí)現(xiàn)with結(jié)構(gòu)的@contextmanager方法詳解
常見(jiàn)with結(jié)構(gòu)
常見(jiàn)的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í)候不希望遺忘一些重要的語(yǔ)句的時(shí)候,可以自己封裝個(gè)with結(jié)構(gòu),比如關(guān)閉數(shù)據(jù)庫(kù)鏈接等情況。
一般實(shí)現(xiàn)方法
with結(jié)構(gòu)一般的實(shí)現(xiàn)方法是在定義類的時(shí)候重載__enter__方法和__exit__方法
比如我們可以通過(guò)如下代碼來(lái)模擬一下上面兩段代碼前者到后者的轉(zhuǎn)化
# -*- coding: utf-8 -*-
class myOpen():
def __init__(self, name, state):
self.f = open(name, state)
# 返回值是with...as...中as出來(lái)的東西,如下面的f
def __enter__(self):
return self.f
# 在with...as...語(yǔ)句塊自動(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)起來(lái)with結(jié)構(gòu)有那么一點(diǎn)點(diǎn)麻煩,那么就進(jìn)入主題吧,有一種逼格又高,又簡(jiǎn)便的方法,先上代碼,仍以打開(kāi)文件為例:
# -*- 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通過(guò)注釋我們可以看到,我們可以通過(guò)給一個(gè)try…finally…結(jié)構(gòu)的函數(shù)頭部加上@contextmanager就可以通過(guò)with…as…結(jié)構(gòu)來(lái)調(diào)用它了
這樣try塊中yield的數(shù)據(jù)被as出來(lái),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)去的,也沒(méi)有理清楚里面的流程,今天整理一下,加深理解,也方便以后查閱,需要的朋友可以參考下2022-11-11
Python中的引用知識(shí)點(diǎn)總結(jié)
在本文里我們給大家整理了關(guān)于Python中的引用知識(shí)點(diǎn)以及相關(guān)代碼總結(jié),需要的朋友們跟著學(xué)習(xí)下。2019-05-05
python數(shù)據(jù)庫(kù)PooledDB連接池初始化使用示例
這篇文章主要為大家介紹了python數(shù)據(jù)庫(kù)PooledDB連接池初始化使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
解決Python中定時(shí)任務(wù)線程無(wú)法自動(dòng)退出的問(wèn)題
今天小編就為大家分享一篇解決Python中定時(shí)任務(wù)線程無(wú)法自動(dòng)退出的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
python實(shí)現(xiàn)用戶管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)用戶管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

