溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python中的上下文管理器怎么創(chuàng)建

發(fā)布時間:2021-11-30 15:39:12 來源:億速云 閱讀:148 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要講解了“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)注!

向AI問一下細(xì)節(jié)

免責(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)容。

AI