使用Python實現(xiàn)with結(jié)構(gòu)的@contextmanager方法詳解
常見with結(jié)構(gòu)
常見的with結(jié)構(gòu)是在進行文件操作時,比如
# 中規(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!")
這個結(jié)構(gòu)的好處,一個是簡潔,一個是當我們對文件操作的邏輯很長的時候,不會因為忘了關閉文件而造成不必要的錯誤。
類似的,當我們在某些時候不希望遺忘一些重要的語句的時候,可以自己封裝個with結(jié)構(gòu),比如關閉數(shù)據(jù)庫鏈接等情況。
一般實現(xiàn)方法
with結(jié)構(gòu)一般的實現(xiàn)方法是在定義類的時候重載__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...語句塊自動執(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方法
好像上面這種方法實現(xiàn)起來with結(jié)構(gòu)有那么一點點麻煩,那么就進入主題吧,有一種逼格又高,又簡便的方法,先上代碼,仍以打開文件為例:
# -*- 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!")
可以看出這里只要定義一個函數(shù),然后在它的頭部加上@contextmanager就好了
這個函數(shù)應該怎么定義呢?我們?nèi)ピ创a里看一下就好,里面給出了詳細的注釋
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
通過注釋我們可以看到,我們可以通過給一個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é)束的時候被執(zhí)行。
到此這篇關于使用Python實現(xiàn)with結(jié)構(gòu)的@contextmanager方法詳解的文章就介紹到這了,更多相關Python實現(xiàn)with結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
pytorch+sklearn實現(xiàn)數(shù)據(jù)加載的流程
這篇文章主要介紹了pytorch+sklearn實現(xiàn)數(shù)據(jù)加載,之前在訓練網(wǎng)絡的時候加載數(shù)據(jù)都是稀里糊涂的放進去的,也沒有理清楚里面的流程,今天整理一下,加深理解,也方便以后查閱,需要的朋友可以參考下2022-11-11python數(shù)據(jù)庫PooledDB連接池初始化使用示例
這篇文章主要為大家介紹了python數(shù)據(jù)庫PooledDB連接池初始化使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08