最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python上下文管理器with塊及@contextmanager的使用

 更新時(shí)間:2026年04月08日 09:13:22   作者:掐死你滴溫柔  
本文主要介紹了上下文管理器和with塊的知識,包括上下文管理器的作用、接口以及__enter__和__exit__方法的用法,同時(shí),還介紹了@contextmanager的用法,它可以簡化上下文管理器的創(chuàng)建過程

上下文管理器和with塊

上下文管理器對象存在的目的是為了管理with塊,就像迭代器的存在是為了管理for循環(huán)一樣

with 語句存在的意義是對一些常用的 try/finally 結(jié)構(gòu)予以簡化。這種結(jié)構(gòu)能夠保障一段代碼在運(yùn)行完成后實(shí)施某項(xiàng)操作,就算該段代碼因?yàn)?return 語句、異?;蛘?sys.exit() 調(diào)用而停止,也依舊執(zhí)行指定的操作。finally 子句中的代碼往往用于釋放重要的資源,亦或是還原臨時(shí)變動(dòng)的狀態(tài)。

上下文管理器接口包含了__enter__以及__exit__這兩個(gè)方法。當(dāng) with 語句開始執(zhí)行的時(shí)候,Python 會(huì)在上下文管理器對象上啟用__enter__方法。待 with 塊運(yùn)行完畢,或者因某些緣由終止之后,Python 會(huì)在上下文管理器對象上調(diào)用__exit__方法。

  • __enter()__方法:當(dāng)進(jìn)入 with 語句時(shí),__enter__() 方法會(huì)被調(diào)用。該方法通常用于執(zhí)行一些準(zhǔn)備工作,并返回一個(gè)資源對象,這個(gè)對象會(huì)被綁定到 as 后的變量名上。
  • __exit()__方法:當(dāng) with 語句塊執(zhí)行結(jié)束時(shí),無論是否發(fā)生了異常,__exit__() 方法都會(huì)被調(diào)用。該方法通常用于執(zhí)行一些清理操作,比如關(guān)閉文件、釋放資源等。如果在 with 語句塊中發(fā)生了異常,異常信息會(huì)作為參數(shù)傳遞給 __exit__() 方法。

下面是一個(gè)精心設(shè)計(jì)的上下文管理器執(zhí)行操作案例

import sys


class LookingGlass:
    def __enter__(self):
        # 將原始的 sys.stdout.write 函數(shù)保存起來
        self.original_wirte = sys.stdout.write
        # 將 sys.stdout.write 函數(shù)替換為 reverse_write 方法
        sys.stdout.write = self.reverse_wirte
        # 返回一個(gè)字符串作為上下文管理器的上下文對象
        return 'QWERTYUIOP'

    def reverse_wirte(self, text):
        # 對傳入的文本進(jìn)行反轉(zhuǎn)后輸出
        return self.original_wirte(text[::-1])

    def __exit__(self, exc_type, exc_val, exc_tb):  # 如果一切正常,那么Python 調(diào)?__exit__ ?法時(shí)傳?的參數(shù)是None, None, None
        # 在退出上下文管理器時(shí),恢復(fù)原始的 sys.stdout.write 函數(shù)
        sys.stdout.write = self.original_wirte
        # 如果發(fā)生的異常是 ZeroDivisionError,輸出相應(yīng)提示信息
        if exc_type is ZeroDivisionError:
            print('Please DO NOT divide by zero!')
            return True  # 返回True,告訴解釋器異常已處理


if __name__ == '__main__':
    with LookingGlass() as what:
        # print(obj)實(shí)質(zhì)就是調(diào)用sys.stdout.write(obj+'\n')
        print("床前明月光")  # 光月明前床
        print("疑是地上霜")  # 霜上地是疑
        print(what)  # POIUYTREWQ
    print(what)  # QWERTYUIOP 處理上下文管理器,輸出的文本正常,不再翻轉(zhuǎn)

解釋器調(diào)用__enter__方法時(shí),除了隱式的self,不需要傳入其他參數(shù),傳給__exit__方法的三個(gè)參數(shù)如下:

  • exc_type:異常類。
  • exc_value:異常實(shí)例。有時(shí)候會(huì)有參數(shù)傳遞給異常構(gòu)造函數(shù),例如錯(cuò)誤消息,這些參數(shù)能夠通過 exc_value.args獲取。
  • exc_tb:trackback對象。

@contextmanager的用法

@contextmanager是一個(gè)十分實(shí)用且巧妙的工具。他將Python3個(gè)功能結(jié)合在一起:函數(shù)裝飾器,生成器以及上下文管理器。

使用@contextmanager能減少創(chuàng)建上下文管理器的樣板代碼,因?yàn)椴挥镁帉懸粋€(gè)類來定義__enter__和__exit__方法,而只要實(shí)現(xiàn)一個(gè)含有yield的生成器,來生成想要__enter__方法返回的值。

在使用@contextmanager裝飾的生成器中,yiled把函數(shù)主體分成兩部分,yield前面的代碼在with塊開始時(shí)(解釋器調(diào)用__enter__方法時(shí))執(zhí)行。yield后面的代碼在with塊結(jié)束時(shí)(解釋器調(diào)用__exit__方法時(shí))執(zhí)行。

繼續(xù)上面的示例:

import sys
import contextlib


@contextlib.contextmanager
def looking_glass():
    original_text = sys.stdout.write

    def reverse_write(text):
        original_text(text[::-1])

    sys.stdout.write = reverse_write
    msg = ''
    # 這里處理異常是因?yàn)槿绻鹷ith塊有異常拋出,Python會(huì)將其捕獲,然后再looking_glass函數(shù)的yield表達(dá)式再次拋出
    # 但是那里又沒有處理錯(cuò)誤的代碼,因此looking_glass函數(shù)將終止執(zhí)行,永遠(yuǎn)無法恢復(fù)成原來的sys.stdout.write方法,導(dǎo)致系統(tǒng)處于無效狀態(tài)。
    try:
        yield 'QWERTYUIOP'
    except ZeroDivisionError:
        msg = 'Please DO NOT divide by zero!'
    finally:
        sys.stdout.write = original_text
        if msg:
            print(msg)


if __name__ == '__main__':
    with looking_glass() as what:
        print("床前明月光")  # 光月明前床
        print("疑是地上霜")  # 霜上地是疑
        print(what)  # POIUYTREWQ
    print(what)  # QWERTYUIOP

其實(shí)@contextlib.contextmanager把函數(shù)包裝成了實(shí)現(xiàn)__enter__和__exit__的類。

那個(gè)類的__enter__方法:

  • 調(diào)用生成器函數(shù),獲取生成器對象,姑且稱之為gen。
  • 調(diào)用next(gen),驅(qū)動(dòng)生成器對象執(zhí)行到y(tǒng)ield關(guān)鍵字位置。
  • 返回next(gen)產(chǎn)生的值,以便把產(chǎn)生的值綁定到as語句的目標(biāo)變量上。

with語句終止,__exit__方法有以下作用:

  • 檢查有沒有異常傳給exc_type,如果有則調(diào)用gen.throw(exception) ,在生成器函數(shù)主體的yield關(guān)鍵字所在的行拋出異常。
  • 否則調(diào)用next(gen),恢復(fù)執(zhí)行生成器函數(shù)主體中yiled后面的代碼。

因此在使用@contextmanager裝飾器是,應(yīng)該把yield放在try/finally語句中,這是不可避免的,因?yàn)槲覀冇肋h(yuǎn)不知道上下文管理器的用戶會(huì)在with塊中做什么。

@contextmanager還有一個(gè)鮮為人知的功能:它裝飾的生成器也可以用做裝飾器。例如:

@looking_glass()
def varse():
    print("舉頭望明月低頭思故鄉(xiāng)")

if __name__ == '__main__':
    varse() # 鄉(xiāng)故思頭低月明望頭舉

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python實(shí)現(xiàn)圖片瀏覽和選擇工具

    Python實(shí)現(xiàn)圖片瀏覽和選擇工具

    這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)一個(gè)圖片瀏覽和選擇工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-05-05
  • 利用Python批量循環(huán)讀取Excel的技巧分享

    利用Python批量循環(huán)讀取Excel的技巧分享

    這篇文章主要為大家詳細(xì)介紹了何用Python批量循環(huán)讀取Excel,文中的示例代碼講解詳細(xì),對我們的學(xué)習(xí)或工作有一定的幫助,感興趣的可以了解一下
    2023-07-07
  • Django中select_related查詢優(yōu)化的具體實(shí)現(xiàn)

    Django中select_related查詢優(yōu)化的具體實(shí)現(xiàn)

    本文介紹了Django ORM中的N+1查詢問題及其解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-12-12
  • python基于plotly實(shí)現(xiàn)畫餅狀圖代碼實(shí)例

    python基于plotly實(shí)現(xiàn)畫餅狀圖代碼實(shí)例

    這篇文章主要介紹了python基于plotly實(shí)現(xiàn)畫餅狀圖代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Python搭建Spark分布式集群環(huán)境

    Python搭建Spark分布式集群環(huán)境

    這篇文章主要介紹了Spark分布式集群環(huán)境搭建基于Python版,Apache Spark 是一個(gè)新興的大數(shù)據(jù)處理通用引擎,提供了分布式的內(nèi)存抽象。100 倍本文而是使用三臺電腦來搭建一個(gè)小型分布式集群環(huán)境安裝,需要的朋友可以參考下
    2019-07-07
  • Python獲取apk文件URL地址實(shí)例

    Python獲取apk文件URL地址實(shí)例

    需要提取apk文件的特定URL地址的朋友可以看一下這個(gè)代碼實(shí)例。
    2013-11-11
  • pandas?groupby?用法實(shí)例詳解

    pandas?groupby?用法實(shí)例詳解

    在日常數(shù)據(jù)分析過程中,經(jīng)常有分組的需求。具體來說,就是根據(jù)一個(gè)或者多個(gè)字段,將數(shù)據(jù)劃分為不同的組,然后進(jìn)行進(jìn)一步分析,比如求分組的數(shù)量,分組內(nèi)的最大值最小值平均值等,下面我們就來看看pandas中的groupby怎么使用,需要的朋友可以參考下
    2022-11-11
  • python處理cookie詳解

    python處理cookie詳解

    Cookie用于服務(wù)器實(shí)現(xiàn)會(huì)話,用戶登錄及相關(guān)功能時(shí)進(jìn)行狀態(tài)管理,本文介紹了使用python處理cookie的方法,需要的朋友可以參考下
    2014-02-02
  • python代碼 輸入數(shù)字使其反向輸出的方法

    python代碼 輸入數(shù)字使其反向輸出的方法

    今天小編就為大家分享一篇python代碼 輸入數(shù)字使其反向輸出的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • 在linux系統(tǒng)下安裝python librtmp包的實(shí)現(xiàn)方法

    在linux系統(tǒng)下安裝python librtmp包的實(shí)現(xiàn)方法

    今天小編就為大家分享一篇在linux系統(tǒng)下安裝python librtmp包的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07

最新評論

晴隆县| 大荔县| 澜沧| 封丘县| 板桥市| 盐城市| 临武县| 嘉禾县| 屯留县| 郑州市| 宿州市| 吴旗县| 姚安县| 黄冈市| 安宁市| 昭觉县| 丰都县| 垫江县| 陵川县| 射洪县| 岑溪市| 白水县| 安乡县| 页游| 衡阳县| 田东县| 祁门县| 清苑县| 林芝县| 万州区| 尉犁县| 锦州市| 随州市| 大理市| 元氏县| 临武县| 宕昌县| 射阳县| 监利县| 明星| 武城县|