Python實(shí)現(xiàn)上下文管理器的方法
問題
你想自己去實(shí)現(xiàn)一個(gè)新的上下文管理器,以便使用with語句。
解決方案
實(shí)現(xiàn)一個(gè)新的上下文管理器的最簡(jiǎn)單的方法就是使用 contexlib 模塊中的 @contextmanager 裝飾器。 下面是一個(gè)實(shí)現(xiàn)了代碼塊計(jì)時(shí)功能的上下文管理器例子:
import time
from contextlib import contextmanager
@contextmanager
def timethis(label):
start = time.time()
try:
yield
finally:
end = time.time()
print('{}: {}'.format(label, end - start))
# Example use
with timethis('counting'):
n = 10000000
while n > 0:
n -= 1
在函數(shù) timethis() 中,yield 之前的代碼會(huì)在上下文管理器中作為 __enter__() 方法執(zhí)行, 所有在 yield 之后的代碼會(huì)作為 __exit__() 方法執(zhí)行。 如果出現(xiàn)了異常,異常會(huì)在yield語句那里拋出。
下面是一個(gè)更加高級(jí)一點(diǎn)的上下文管理器,實(shí)現(xiàn)了列表對(duì)象上的某種事務(wù):
@contextmanager def list_transaction(orig_list): working = list(orig_list) yield working orig_list[:] = working
這段代碼的作用是任何對(duì)列表的修改只有當(dāng)所有代碼運(yùn)行完成并且不出現(xiàn)異常的情況下才會(huì)生效。 下面我們來演示一下:
>>> items = [1, 2, 3]
>>> with list_transaction(items) as working:
... working.append(4)
... working.append(5)
...
>>> items
[1, 2, 3, 4, 5]
>>> with list_transaction(items) as working:
... working.append(6)
... working.append(7)
... raise RuntimeError('oops')
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: oops
>>> items
[1, 2, 3, 4, 5]
>>>
討論
通常情況下,如果要寫一個(gè)上下文管理器,你需要定義一個(gè)類,里面包含一個(gè) __enter__() 和一個(gè) __exit__() 方法,如下所示:
import time
class timethis:
def __init__(self, label):
self.label = label
def __enter__(self):
self.start = time.time()
def __exit__(self, exc_ty, exc_val, exc_tb):
end = time.time()
print('{}: {}'.format(self.label, end - self.start))
盡管這個(gè)也不難寫,但是相比較寫一個(gè)簡(jiǎn)單的使用 @contextmanager 注解的函數(shù)而言還是稍顯乏味。
@contextmanager 應(yīng)該僅僅用來寫自包含的上下文管理函數(shù)。 如果你有一些對(duì)象(比如一個(gè)文件、網(wǎng)絡(luò)連接或鎖),需要支持 with 語句,那么你就需要單獨(dú)實(shí)現(xiàn) __enter__() 方法和 __exit__() 方法。
以上就是Python實(shí)現(xiàn)上下文管理器的方法的詳細(xì)內(nèi)容,更多關(guān)于Python實(shí)現(xiàn)上下文管理器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用tensorflow根據(jù)輸入更改tensor shape
這篇文章主要介紹了使用tensorflow根據(jù)輸入更改tensor shape,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06
python函數(shù)map()和partial()的知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家分享了關(guān)于python函數(shù)map()和partial()的知識(shí)點(diǎn)總結(jié),需要的朋友們可以參考下。2020-05-05
python中使用sys模板和logging模塊獲取行號(hào)和函數(shù)名的方法
這篇文章主要介紹了python中使用sys模板和logging模塊獲取行號(hào)和函數(shù)名的方法,需要的朋友可以參考下2014-04-04
python框架flask入門之路由及簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了python框架flask入門路由及路由簡(jiǎn)單實(shí)現(xiàn)方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
利用Python的pandas數(shù)據(jù)處理包將寬表變成窄表
這篇文章主要介紹了利用Python的pandas數(shù)據(jù)處理包將寬表變成窄表,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09

