日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 默认站点!

默认站点

當前位置: 首頁 >

Python 上下文管理器和 with 语句

發布時間:2023/11/28 33 豆豆
默认站点 收集整理的這篇文章主要介紹了 Python 上下文管理器和 with 语句 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 上下文管理器概念

什么是 Python 的上下文管理器(Context Managers)呢?
?
含有 __enter____exit__ 方法的對象就是。上下文管理器存在的目的是管理 with 語句,就像是迭代器的存在是為了管理 for 語句一樣。

with 上下文管理器:語句體

2. with 語句

with 遇到上下文管理器,就會在執行語句體之前,先執行上下文管理器的 __enter__ 方法,然后再執行語句體,執行完語句體后,最后執行 __exit__ 方法。舉個例子:

class Foo(object):def __init__(self):print('把大象放冰箱總共分幾步?')def __enter__(self):print('把冰箱門打開')def __exit__(self, exc_type, exc_val, exc_tb):print('把冰箱門關上')obj = Foo()with obj:print('把大象放進去')

輸出:

把大象放冰箱總共分幾步?
把冰箱門打開
把大象放進去
把冰箱門關上

with 有一個很重要的作用是簡化 try/finally 模式,無論何種異常發生,finally 字句都會執行。
?
通常 finally子句中的代碼用于釋放重要的資源,或者還原臨時變更的狀態。比如,不管大象能不能裝進冰箱,最終 finally你都得把冰箱門關上,用代碼解釋就是:

class Foo(object):def __init__(self):print('把大象放冰箱總共分幾步?')def __enter__(self):print('把冰箱門打開')def __exit__(self, exc_type, exc_val, exc_tb):print('把冰箱門關上')obj = Foo()with obj:raise ImportError # 這里發生嚴重的錯誤,這段程序崩潰了print('把大象放進去')

輸出結果:

把大象放冰箱總共分幾步?
把冰箱門打開
把冰箱門關上
Traceback (most recent call last):File "char_1.py", line 15, in <module>raise ImportError
ImportError

有了 with 保駕護航,裝大象的程序崩潰了,也能把冰箱門關上。

3. 上下文管理器寫法

Python 提供了更簡便的上下文管理器寫法,使用 @contextmanager。在使用 @contextmanager 裝飾的生成器中,yield 語句的作用是把所在函數分成兩部分:

  • yield 語句前面的代碼在 with 塊開始時執行;
  • yield 語句后面的代碼在 with 塊結束時執行;

那么上面的例子就可以簡寫成為:

from contextlib import contextmanager@contextmanager
def fridge_operation():print('把大象放冰箱總共分幾步?')print('把冰箱門打開')yieldprint('把冰箱門關上')def put_elephant_in_fridge():print('把大象放進去')with fridge_operation() :put_elephant_in_fridge()

輸出:

把大象放冰箱總共分幾步?
把冰箱門打開
把大象放進去
把冰箱門關上

但需要特別注意的是,如果使用 @contextmanager 來實現上下文管理器,要把 yield 語句放在 try/finally語句中(或者放在 with 語句中),個人覺得 Python 在這一點上把 @contextmanager 變的十分具有迷惑性,它可以把生成器函數變成上下文管理器,但是它不能聯手與 with 默認完成 finally 功能,用代碼說明:

from contextlib import contextmanager@contextmanager
def fridge_operation():print('把大象放冰箱總共分幾步?')print('把冰箱門打開')yieldprint('把冰箱門關上')def put_elephant_in_fridge():print('把大象放進去')with fridge_operation() :raise ImportError # 這里發生嚴重的錯誤,這段程序崩潰了put_elephant_in_fridge()

輸出:

把大象放冰箱總共分幾步?
把冰箱門打開
Traceback (most recent call last):File "char_1.py", line 15, in <module>raise ImportError
ImportError

發現了么?冰箱門沒關上。冰箱門沒關上,我要你上下文管理器有什么用?所以我們需要把 yield 語句放在 try/finally 語句中,如下:

from contextlib import contextmanager@contextmanager
def fridge_operation():print('把大象放冰箱總共分幾步?')print('把冰箱門打開')try:yieldfinally:print('把冰箱門關上')with fridge_operation():raise ImportErrorprint('把大象放進去')

輸出:

把大象放冰箱總共分幾步?
把冰箱門打開
把冰箱門關上
Traceback (most recent call last):File "char_1.py", line 13, in <module>raise ImportError
ImportError

至此,@contextmanager 巧妙的將三個不同的 Python 特性結合到了一起:函數裝飾器,生成器和 with 語句。
?

參考:
https://book.pythontips.com/en/latest/context_managers.html

總結

以上是默认站点為你收集整理的Python 上下文管理器和 with 语句的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得默认站点網站內容還不錯,歡迎將默认站点推薦給好友。