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

Python上下文管理器和with塊詳解

 更新時間:2017年09月09日 15:05:26   作者:zhexiao27  
這篇文章主要為大家詳細介紹了Python上下文管理器和with塊的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下

上下文管理器和with塊,具體內(nèi)容如下

上下文管理器對象存在的目的是管理 with 語句,就像迭代器的存在是為了管理 for 語句一樣。

with 語句的目的是簡化 try/finally 模式。這種模式用于保證一段代碼運行完畢后執(zhí)行某項操作,即便那段代碼由于異常、 return 語句或 sys.exit() 調(diào)用而中止,也會執(zhí)行指定的操作。 finally 子句中的代碼通常用于釋放重要的資源,或者還原臨時變更的狀態(tài)。

==上下文管理器協(xié)議包含enter和exit兩個方法==。 with 語句開始運行時,會在上下文管理器對象上調(diào)用enter方法。 with 語句運行結(jié)束后,會在上下文管理器對象上調(diào)用exit方法,以此扮演 finally 子句的角色。

==執(zhí)行 with 后面的表達式得到的結(jié)果是上下文管理器對象,把值綁定到目標變量上(as 子句)是在上下文管理器對象上調(diào)用enter方法的結(jié)果==。with 語句的 as 子句是可選的。對 open 函數(shù)來說,必須加上 as子句,以便獲取文件的引用。不過,有些上下文管理器會返回 None,因為沒什么有用的對象能提供給用戶。

with open('mirror.py') as fp:
  ...

自定義的上下文類:

class A:
  def __init__(self, name):
    self.name = name

  def __enter__(self):
    print('enter')
    return self.name

  def __exit__(self, exc_type, exc_val, exc_tb):
    print('gone')

with A('xiaozhe') as dt:
  print(dt)

contextlib模塊

contextlib 模塊中還有一些類和其他函數(shù),使用范圍更廣。

closing:如果對象提供了 close() 方法,但沒有實現(xiàn)enter/exit協(xié)議,那么可以使用這個函數(shù)構建上下文管理器。
suppress:構建臨時忽略指定異常的上下文管理器。
@contextmanager:==這個裝飾器把簡單的生成器函數(shù)變成上下文管理器==,這樣就不用創(chuàng)建類去實現(xiàn)管理器協(xié)議了。
ContextDecorator:這是個基類,用于定義基于類的上下文管理器。這種上下文管理器也能用于裝飾函數(shù),在受管理的上下文中運行整個函數(shù)
ExitStack:這個上下文管理器能進入多個上下文管理器。 with 塊結(jié)束時, ExitStack 按照后進先出的順序調(diào)用棧中各個上下文管理器的exit方法。

==使用最廣泛的是 @contextmanager 裝飾器,因此要格外留心。這個裝飾器也有迷惑人的一面,因為它與迭代無關,卻要使用 yield 語句==。

使用@contextmanager

@contextmanager 裝飾器能減少創(chuàng)建上下文管理器的樣板代碼量,不用編寫一個完整的類定義enter和exit方法,而只需實現(xiàn)有一個 yield 語句的生成器,生成想讓enter方法返回的值。

在使用 @contextmanager 裝飾的生成器中, yield 語句的作用是把函數(shù)的定義體分成兩部分: ==yield 語句前面的所有代碼在 with 塊開始時(即解釋器調(diào)用enter方法時)執(zhí)行, yield 語句后面的代碼在 with 塊結(jié)束時(即調(diào)用exit方法時)執(zhí)行==。

import contextlib

@contextlib.contextmanager
def test(name):
  print('start')
  yield name
  print('end')

with test('zhexiao123') as dt:
  print(dt)
  print('doing something')

實現(xiàn)原理

contextlib.contextmanager 裝飾器會把函數(shù)包裝成實現(xiàn)enter和exit方法的類。類的名稱是 _GeneratorContextManager。

這個類的enter方法有如下作用:
1. 調(diào)用生成器函數(shù),保存生成器對象(這里把它稱為 gen)。
2. 調(diào)用 next(gen),執(zhí)行到 yield 關鍵字所在的位置。
3. 返回 next(gen) 產(chǎn)出的值,以便把產(chǎn)出的值綁定到 with/as 語句中的目標變量上。

with 塊終止時,exit方法會做以下幾件事:

1. 檢查有沒有把異常傳給 exc_type;如果有,調(diào)用 gen.throw(exception),在生成器函數(shù)定義體中包含 yield 關鍵字的那一行拋出異常。
2. 否則,調(diào)用 next(gen),繼續(xù)執(zhí)行生成器函數(shù)定義體中 yield 語句之后的代碼。

異常處理

為了告訴解釋器異常已經(jīng)處理了,exit方法會返回 True,此時解釋器會壓制異常。如果exit方法沒有顯式返回一個值,那么解釋器得到的是 None,然后向上冒泡異常。

使用 @contextmanager 裝飾器時,默認的行為是相反的:裝飾器提供的exit方法假定發(fā)給生成器的所有異常都得到處理了,因此應該壓制異常。 如果不想讓 @contextmanager 壓制異常,必須在被裝飾的函數(shù)中顯式重新拋出異常。

上面的代碼有個bug:如果在 with 塊中拋出了異常, Python 解釋器會將其捕獲,然后在 test 函數(shù)的 yield 表達式里再次拋出。但是,那里沒有處理錯誤的代碼,因此 test 函數(shù)會中止。

使用 @contextmanager 裝飾器時,要把 yield 語句放在 try/finally 語句中,因為我們永遠不知道上下文管理器的用戶會在 with 塊中做什么。

import contextlib

@contextlib.contextmanager
def test(name):
  print('start')

  try:
    yield name
  except:
    raise ValueError('error')
  finally:
    print('end')

with test('zhexiao123') as dt:
  print(dt)
  print('doing something')

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Python pandas庫中的isnull()詳解

    Python pandas庫中的isnull()詳解

    今天小編就為大家分享一篇Python pandas庫中的isnull()詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • C# DataGridView行列轉(zhuǎn)換的具體實現(xiàn)

    C# DataGridView行列轉(zhuǎn)換的具體實現(xiàn)

    本文主要介紹了C# DataGridView行列轉(zhuǎn)換的具體實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • python實現(xiàn)圖像識別功能

    python實現(xiàn)圖像識別功能

    這篇文章主要為大家詳細介紹了python實現(xiàn)圖像識別功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Python?matplotlib繪制灰度和彩色直方圖

    Python?matplotlib繪制灰度和彩色直方圖

    Matplotlib是Python的繪圖庫,它能讓使用者很輕松地將數(shù)據(jù)圖形化,并且提供多樣化的輸出格式。本文將為大家介紹如何用matplotlib繪制灰度和彩色直方圖,感興趣的朋友可以學習一下
    2021-12-12
  • Python 通過URL打開圖片實例詳解

    Python 通過URL打開圖片實例詳解

    這篇文章主要介紹了Python 通過URL打開圖片實例詳解的相關資料,需要的朋友可以參考下
    2017-06-06
  • python構造IP報文實例

    python構造IP報文實例

    這篇文章主要介紹了python構造IP報文實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • Python bisect模塊原理及常見實例

    Python bisect模塊原理及常見實例

    這篇文章主要介紹了Python bisect模塊原理及常見實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • django rest framework使用django-filter用法

    django rest framework使用django-filter用法

    這篇文章主要介紹了django rest framework使用django-filter用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • python中函數(shù)默認值使用注意點詳解

    python中函數(shù)默認值使用注意點詳解

    下面小編就為大家?guī)硪黄猵ython中函數(shù)默認值使用注意點詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • Python基于template實現(xiàn)字符串替換

    Python基于template實現(xiàn)字符串替換

    這篇文章主要介紹了Python基于template實現(xiàn)字符串替換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11

最新評論

本溪市| 石阡县| 云和县| 晋州市| 册亨县| 德化县| 叶城县| 江安县| 共和县| 岱山县| 宁明县| 涿州市| 高州市| 新泰市| 长丰县| 赤城县| 闽清县| 建水县| 册亨县| 会东县| 宁夏| 理塘县| 平邑县| 大荔县| 杭锦旗| 左贡县| 芒康县| 华安县| 崇礼县| 桃源县| 凤山市| 禹城市| 札达县| 建平县| 大渡口区| 雅安市| 玛纳斯县| 河东区| 依兰县| 福建省| 松桃|