您好,登錄后才能下訂單哦!
這篇文章主要講解了“Python中的上下文管理器怎么創(chuàng)建”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python中的上下文管理器怎么創(chuàng)建”吧!
通常我們希望把一些操作放到一個代碼塊中,在代碼塊中執(zhí)行時就可以保持在某種運行狀態(tài),而當(dāng)離開該代碼塊時就執(zhí)行另一個操作,結(jié)束當(dāng)前狀態(tài);所以,簡單來說,上下文管理器的目的就是規(guī)定對象的使用范圍,如果超出范圍就采取“處理”。Python提供了不同的方法來管理執(zhí)行時間。例如,您可以使用Python的內(nèi)置timeit模塊來管理一小段代碼的執(zhí)行時間。
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.3018611848820001
但是,timeit.timeit
函數(shù)僅接受字符串,如果要管理比較復(fù)雜的函數(shù)時會有局限性。以下示例向您展示如何使用timeit
模塊運行和管理函數(shù)。
def test():
"""Stupid test function"""
L = [i for i in range(100)]
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
盡管它可以工作,但看起來并不是真正的pythonic。管理執(zhí)行時間的另一種方法是利用Python的內(nèi)置cProfile
模塊,但是并不建議用它,實際上它不是很精確,這只是一種變通方法,可讓您了解某些代碼段需要執(zhí)行多長時間。您可以通過以下方式使用它:
>>> python -m cProfile <file_name.py>
既然上面的兩種方法都不是非常Pythonic并且都有缺陷,那么我們?nèi)绾螌崿F(xiàn)一個比較完美的解決方案呢?
其實很簡單:我們只要能拿到程序開始執(zhí)行和結(jié)束執(zhí)行的時間就可以了,下面介紹具體方法,Python有一個內(nèi)置模塊可供我們使用:time
。
>>> import time
>>> start = time.time()
>>> # do some stuff
>>> end = time.time()
>>> print(f"Elapsed Time: {end - start}")
但是這樣寫不是很方便。我們可以創(chuàng)建一個上下文管理器。
創(chuàng)建一個上下文管理器
使用Python創(chuàng)建上下文管理器有兩種不同方法,我們將研究兩種方法來實現(xiàn)此目的:基于類和基于生成器的上下文管理器。
基于類的上下文管理器
要創(chuàng)建基于類的上下文管理器,需要先實現(xiàn)魔法變量__enter__
和__exit__
。進(jìn)入上下文(或代碼塊)時調(diào)用第一個,離開上下文時調(diào)用后者。
有了這些準(zhǔn)備,我們就可以來創(chuàng)建一個實現(xiàn)這兩種方法的Timer
類。進(jìn)入代碼塊時,我們希望獲取當(dāng)前時間并將其保存到表示開始的變量中。如果我們離開代碼塊,我們想獲取當(dāng)前時間并從中減去開始時間。結(jié)果被打印出來。
為了自定義輸出,我們讓用戶指定一個語句,該語句在經(jīng)過的時間之前打印。以下要點向您展示了一個即用型的類。
from time import time
class Timer(object):
def __init__(self, description):
self.description = description
def __enter__(self):
self.start = time()
def __exit__(self, type, value, traceback):
self.end = time()
print(f"{self.description}: {self.end - self.start}")
with Timer("List Comprehension Example"):
s = [x for x in range(10_000_000)]
基于生成器的上下文管理器
基于生成器的方法更加簡單。我們可以創(chuàng)建一個包含程序流程的生成器函數(shù)(獲取開始和結(jié)束時間以及打印經(jīng)過的時間)。@contextmanager
裝飾器通過使用GeneratorContextManager
對象包裝生成器,將生成器功能轉(zhuǎn)換為適當(dāng)?shù)纳舷挛墓芾砥鳌?/p>
from contextlib import contextmanager
from time import time
@contextmanager
def timing(description: str) -> None:
start = time()
yield
ellapsed_time = time() - start
print(f"{description}: {ellapsed_time}")
with timing("List Comprehension Example"):
s = [x for x in range(10_000_000)]
如果執(zhí)行了with
后面的代碼塊,將跳回到y(tǒng)ield關(guān)鍵字之后的位置繼續(xù)執(zhí)行。感謝各位的閱讀,以上就是“Python中的上下文管理器怎么創(chuàng)建”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Python中的上下文管理器怎么創(chuàng)建這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。