欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Python中的上下文管理器原理

 更新時間:2023年03月11日 14:04:26   作者:一根頭發(fā)學(xué)一年  
這篇文章主要為大家詳細(xì)介紹了Python中的上下文管理器的原理與使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

with語句

在我們?nèi)粘J褂脠鼍爸?,?jīng)常會操作一些資源,比如文件對象、數(shù)據(jù)庫連接、Socket連接等,資源操作完了之后,不管操作的成功與否,最重要的事情就是關(guān)閉該資源,否則資源打開太多而沒有關(guān)閉,程序會報錯,以文件操作為例,通常我們會這樣寫:

f = open('file.txt', 'w')
try:
    f.write("Hello")
finally:
    f.close()

但既然close方法是必須的操作,那就沒必要顯式地調(diào)用,所以Python給我們提供了一種更優(yōu)雅的方式,使用with語句:

with open('file.txt', 'w') as f:
    f.write("Hello")

在退出with語句下的代碼塊之后,f 對象會自動執(zhí)行自己的close方法,實(shí)現(xiàn)資源的釋放,簡潔優(yōu)雅。

上下文管理器原理

上下文管理器實(shí)際是內(nèi)部實(shí)現(xiàn)了__enter__和__exit__方法的對象。

當(dāng)我們使用with語法時:

__enter__()方法:返回一個值,可以將它賦值給as后面的對象,例如上面的中的f;

__exit__()方法:with語句退出或者發(fā)送異常時會執(zhí)行這個方法。

1、__enter__方法說明

上下文管理器的__enter__方法是可以帶返回值的,默認(rèn)返回None,這個返回值通過with…as…中的 as 賦給它后面的那個變量,所以 with EXPR as VAR 就是將EXPR對象__enter__方法的返回值賦給 VAR。

當(dāng)然with...as...并非固定組合,單獨(dú)使用with...也是可以的,上下文管理器的__enter__方法還是正常執(zhí)行,只是這個返回值并沒有賦給一個變量,with下面的代碼塊也不能使用這個返回值。

2、__exit__方法說明

上下文管理器的__exit__方法接收3個參數(shù)exc_type、exc_val、exc_tb,如果代碼塊BLOCK發(fā)生了異常e并退出,這3個參數(shù)分別為type(e)、str(e)、e.__traceback__,否則都為None。

同樣__exit__方法也是可以帶返回值的,這個返回值應(yīng)該是一個布爾類型True或False,默認(rèn)為None(即False)。如果為False,異常會被拋出,用戶需要進(jìn)行異常處理。如果為True,則表示忽略該異常。

一個上下文管理器一般使用如下:

with EXPR as VAR:
    BLOCK

上述代碼的執(zhí)行過程等價于:

ContextManager = EXPR
VAR = ContextManager.__enter__()
try:
    BLOCK
finally:
    ContextManager.__exit__()

f 對象就是把自己的close方法定義在了它的__exit__方法內(nèi)部,實(shí)現(xiàn)了代碼塊BLOCK執(zhí)行完之后自動關(guān)閉自身。

自定義上下文管理器

下面我們定義一個文件類,內(nèi)部實(shí)現(xiàn)了__enter__和__exit__兩個方法:

class File:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        print("進(jìn)入")
        self.f = open(self.filename, self.mode)
        return self.f

    def __exit__(self, exc_type=None, exc_val=None, exc_tbs=None):
        print("退出")
        self.f.close()

這時候File類就是一個上下文管理器

我們分別通過 with語句 和 try/finally語句 使用File類對文件進(jìn)行寫入操作

通過with語句執(zhí)行:

with File('file.txt', 'w') as f:
    print("正在寫入...")
    f.write('Hello')

控制臺輸出:

進(jìn)入
正在寫入...
退出

并得到了一個寫了 Hello 的 file.txt 文件

通過try/finally語句執(zhí)行:

ContextManager = File('file.txt', 'w')
VAR = ContextManager .__enter__()
try:
    print("正在寫入...")
    VAR.write('Hello')
finally:
    ContextManager.__exit__()

控制臺輸出:

進(jìn)入
正在寫入...
退出

并得到了一個寫了 Hello 的 file.txt 文件

兩者輸出一致,所以驗(yàn)證了二中執(zhí)行過程的等價關(guān)系是正確的。

contextmanager 裝飾器

Python還提供了一個contextmanager裝飾器,允許用戶將一個生成器定義為上下文管理器,該裝飾器將生成器中的代碼通過yield語句分成兩部分,yield之前的代碼為__enter__方法,yield之后的代碼為__exit__方法,yield的返回值即__enter__方法的返回值,用于賦給as后的變量。

下面我們通過contextmanager裝飾器也實(shí)現(xiàn)一個關(guān)于文件的上下文管理器:

from contextlib import contextmanager

@contextmanager
def open_file(filename, mode):
    print('進(jìn)入')
    f = open(filename, mode)
    try:
        yield f
    finally:
        print('退出')
        f.close()

說明:這里使用 try/finally 是確保yield的過程中就算出現(xiàn)異常,文件也能正常關(guān)閉,當(dāng)然這里也能處理異常,使用 try/except/finally 即可。

通過with語句執(zhí)行:

with open_file('file.txt', 'w') as f:
    print("正在寫入...")
    f.write('Hello')

執(zhí)行結(jié)果跟之前的上下文管理器執(zhí)行結(jié)果一致,說明contextmanager裝飾器也能定義一個上下文管理器。

到此這篇關(guān)于詳解Python中的上下文管理器原理的文章就介紹到這了,更多相關(guān)Python上下文管理器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決pycharm安裝第三方庫失敗的問題

    解決pycharm安裝第三方庫失敗的問題

    這篇文章主要介紹了pycharm安裝第三方庫失敗的解決方法,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • python實(shí)現(xiàn)列表中最大最小值輸出的示例

    python實(shí)現(xiàn)列表中最大最小值輸出的示例

    今天小編就為大家分享一篇python實(shí)現(xiàn)列表中最大最小值輸出的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • Python實(shí)現(xiàn)獲取亂序列表排序后的新下標(biāo)的示例

    Python實(shí)現(xiàn)獲取亂序列表排序后的新下標(biāo)的示例

    本文主要介紹了Python實(shí)現(xiàn)獲取亂序列表排序后的新下標(biāo)的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Python練習(xí)之操作SQLite數(shù)據(jù)庫

    Python練習(xí)之操作SQLite數(shù)據(jù)庫

    這篇文章主要介紹了Python練習(xí)之操作SQLite數(shù)據(jù)庫,主要通過三個問題如何創(chuàng)建SQLite數(shù)據(jù)庫?如何向SQLite表中插入數(shù)據(jù)?如何查詢SQLite表中的數(shù)據(jù)?展開文章主題詳情,需要的朋友可以參考一下
    2022-06-06
  • python中的%?是什么意思,起到什么作用呢

    python中的%?是什么意思,起到什么作用呢

    %Y會被無世紀(jì)的年份所替代,%m會被01到12之間的一個十進(jìn)制月份數(shù)替代,其他依次類推,%在python的格式化輸出,有轉(zhuǎn)換字符的作用,本文給大家講解python中的%?是什么意思,起到什么作用,感興趣的朋友一起看看吧
    2022-12-12
  • python入門教程 python入門神圖一張

    python入門教程 python入門神圖一張

    這篇文章主要介紹了Python 10分鐘入門教程,分享一張Python入門神圖一張,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Python使用CMD模塊更優(yōu)雅的運(yùn)行腳本

    Python使用CMD模塊更優(yōu)雅的運(yùn)行腳本

    這篇文章主要介紹了Python使用CMD模塊更優(yōu)雅的運(yùn)行腳本的方法,實(shí)例分析了Python中cmd模塊的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-05-05
  • Python中拆包的實(shí)現(xiàn)

    Python中拆包的實(shí)現(xiàn)

    拆包是一個非常實(shí)用且常見的操作,它能夠簡化代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07
  • baselines示例程序train_cartpole.py的ImportError

    baselines示例程序train_cartpole.py的ImportError

    這篇文章主要為大家介紹了baselines示例程序train_cartpole.py的ImportError引入錯誤詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • python django下載大的csv文件實(shí)現(xiàn)方法分析

    python django下載大的csv文件實(shí)現(xiàn)方法分析

    這篇文章主要介紹了python django下載大的csv文件實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Django框架下載csv大文件的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2019-07-07

最新評論