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

python 上下文管理器及自定義原理解析

 更新時間:2019年11月19日 14:57:13   作者:-零  
這篇文章主要介紹了python 上下文管理器原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

這篇文章主要介紹了python 上下文管理器原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

Python 提供了 with 語法用于簡化資源操作的后續(xù)清除操作,是 try/finally 的替代方法,實現(xiàn)原理建立在上下文管理器之上。

Python 提供了一個 contextmanager 裝飾器,更進一步簡化上下管理器的實現(xiàn)方式。

上下文管理器是Python2.5之后才出現(xiàn)的概念。上下文管理器規(guī)定了某個對象的使用范圍,當(dāng)進入或者離開了使用范圍,都會有相應(yīng)的一些調(diào)用,比如代碼塊開始時執(zhí)行一些準備,代碼塊結(jié)束時結(jié)束一些操作。它更多的是用于資源的分配和釋放上,即在開始時分配資源,結(jié)束時釋放一些資源。比如在執(zhí)行數(shù)據(jù)庫查詢時要建立連接,查詢結(jié)束后要釋放連接;寫文件時要先打開文件,寫結(jié)束后,要關(guān)閉文件等等。還有,就是資源的加鎖和解鎖,比如在使用多線程時,可能會用到加鎖和解鎖。

上下文管理器可以通過使用更可讀、更精簡的代碼實現(xiàn)資源的分配與釋放。
復(fù)制代碼

with的使用

對于上下文管理器的使用,最常見的是使用with語句,with語句可構(gòu)建資源的分配與釋放的語法糖。

因為with語句就是為支持上下文管理器而存在的,使用上下文管理協(xié)議的方法包裹一個代碼塊(with語句體)的執(zhí)行,并為try...except...finally提供了一個方便使用的封裝。

一般語法:

def load_data(filename):
  f = file(filename,'w')
  try:
   f.write('test file')
  finally:
   f.close()

使用with:

# 使用with
with open('test.txt', 'w') as f:
  f.write('Python')

通過 with 語句在編寫代碼時,會使代碼變得更加簡潔,不用再去關(guān)閉文件。

我們并不需要寫文件的關(guān)閉操作,文件會在使用完后自動關(guān)閉。

with的執(zhí)行原理

實際上,在文件操作時,并不是不需要寫文件的關(guān)閉,而是文件的關(guān)閉操作在 with 的上下文管理器中的協(xié)議方法里已經(jīng)寫好了。當(dāng)文件操作執(zhí)行完成后, with語句會自動調(diào)用上下文管理器里的關(guān)閉語句來關(guān)閉文件資源。

上下文管理協(xié)議(context management protocol)
ContextManager ,上下文是 context 直譯的叫法,在程序中用來表示代碼執(zhí)行過程中所處的前后環(huán)境。

上下文管理器中有 __enter__ 和 __exit__ 兩個方法,以with為例子,__enter__ 方法會在執(zhí)行 with 后面的語句時執(zhí)行,一般用來處理操作前的內(nèi)容。比如一些創(chuàng)建對象,初始化等;__exit__ 方法會在 with 內(nèi)的代碼執(zhí)行完畢后執(zhí)行,一般用來處理一些善后收尾工作,比如文件的關(guān)閉,數(shù)據(jù)庫的關(guān)閉等。

上下文管理協(xié)議包括兩個方法:

contextmanager.__enter__() 從該方法進入運行時上下文,并返回當(dāng)前對象或者與運行時上下文相關(guān)的其他對象。如果with語句有as關(guān)鍵詞存在,返回值會綁定在as后的變量上。

contextmanager.__exit__(exc_type, exc_val, exc_tb) 退出運行時上下文,并返回一個布爾值標示是否有需要處理的異常。如果在執(zhí)行with語句體時發(fā)生異常,那退出時參數(shù)會包括異常類型、異常值、異常追蹤信息,否則,3個參數(shù)都是None。

with語句的語法如下:

with EXPR as VAR:
  BLOCK

with和as是關(guān)鍵詞,EXPR就是上下文表達式,是任意表達式(一個表達式,不是表達式列表),VAR是賦值的目標變量。"as VAR"是可選的。

上述語句的底層實現(xiàn)可以這樣描述:

mgr = (EXPR)
exit = type(mgr).__exit__ # 并沒有調(diào)用
value = type(mgr).__enter__(mgr)
exc = True
try:
  try:
    VAR = value # 如果有"as VAR"
    BLOCK
  except:
    # 這里會處理異常
    exc = False
    if not exit(mgr, *sys.exc_info()):
      raise
    # 如果__exit__返回值是false,異常將被傳播;如果返回值是真,異常將被終止
finally:
  if exc:
    exit(mgr, None, None, None)

這樣with語句的執(zhí)行過程就很清楚了。

  • 執(zhí)行上下文表達式,獲取上下文管理器
  • 加載上下文管理器的__exit__()方法以備后期調(diào)用
  • 調(diào)用上下文管理器的__enter__()方法
  • 如果with語句有指定目標變量,將從__enter__()方法獲取的相關(guān)對象賦值給目標變量
  • 執(zhí)行with語句體
  • 調(diào)用上下文管理器的__exit__()方法,如果是with語句體造成的異常退出,那異常類型、異常值、異常追蹤信息將被傳給__exit__(),否則,3個參數(shù)都是None。

也可以將多個表達式組織在一起。

with A() as a, B() as b:
BLOCK

它等價于

with A() as a: with B() as b: BLOCK

注:多上下文表達式是從python 2.7開始支持的

自定義上下文管理器(模擬with打開文件)

要實現(xiàn)一個自定義的上下文管理器,肯定要實現(xiàn)兩個方法,一是進入對象范圍時的準備工作,二是離開對象范圍時的結(jié)束工作。

Python提供了兩個類的方法分別實現(xiàn)上述功能:

  • __enter__ 進入對象范圍時(一般代碼塊開始)被調(diào)用;
  • __exit__ 離開對象范圍時(代碼塊結(jié)束)唄調(diào)用;

因此,一個Python類,只要實現(xiàn)了上述兩種方法,就可以說是一個上下文管理器。

class MyOpen(object):
  def __init__(self,path,mode):
    # 記錄要操作的文件路徑和模式
    self.__path = path
    self.__mode = mode
 
  def __enter__(self):
    print('代碼執(zhí)行到了__enter__......')
    # 打開文件
    self.__handle = open(self.__path,self.__mode)
    # 返回打開的文件對象引用, 用來給 as 后的變量f賦值
    return self.__handle
 
  # 退出方法中,用來實現(xiàn)善后處理工作
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('代碼執(zhí)行到了__exit__......')   
    self.__handle.close()
 
# a+ 打開一個文件用于讀寫。如果該文件已存在,文件指針將會放在文件的結(jié)尾。文件打開時會是追加模式。如果該文件不存在,創(chuàng)建新文件用于讀寫。
with MyOpen('test.txt','a+') as f:
  # 創(chuàng)建寫入文件
  f.write("Hello Python!!!")
  print("文件寫入成功")

通過執(zhí)行順序,可以看到文件寫入操作執(zhí)行完之后,自動調(diào)用了__exit__方法,做了善后處理工作。

代碼執(zhí)行到了__enter__......
文件寫入成功
代碼執(zhí)行到了__exit__...... 
 

__exit__方法的參數(shù)

__exit__ 方法中有三個參數(shù),用來接收處理異常,如果代碼在運行時發(fā)生異常,異常會被保存到這里。

exc_type : 異常類型

exc_val : 異常值

exc_tb : 異?;厮葑粉?/p>

# 編寫兩個數(shù)做除法的程序,然后給除數(shù)穿入0
class MyCount(object):
  # 接收兩個參數(shù)
  def __init__(self,x, y):
    self.__x = x
    self.__y = y
  # 返回一個地址(實質(zhì)是被as后的變量接收),實例對象就會執(zhí)行MyCount中的方法:div()
  def __enter__(self):
    print('代碼執(zhí)行到了__enter__......')
    return self
  def __exit__(self, exc_type, exc_val, exc_tb):
    print("代碼執(zhí)行到了__exit__......")
    if exc_type == None:
      print('程序沒問題')
    else:
      print('程序有問題,如果你能你看懂,問題如下:')
      print('Type: ', exc_type)
      print('Value:', exc_val)
      print('TreacBack:', exc_tb)
 
    # 返回值決定了捕獲的異常是否繼續(xù)向外拋出
    # 如果是 False 那么就會繼續(xù)向外拋出,程序會看到系統(tǒng)提示的異常信息
    # 如果是 True 不會向外拋出,程序看不到系統(tǒng)提示信息,只能看到else中的輸出
    return True
 
  def div(self):
    print("代碼執(zhí)行到了除法div")
    return self.__x / self.__y
with MyCount(1, 0) as mc:
  mc.div()

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

相關(guān)文章

  • python字典多條件排序方法實例

    python字典多條件排序方法實例

    這篇文章主要介紹了python字典多條件排序方法實例,分別使用lambda和itemgetter實現(xiàn),需要的朋友可以參考下
    2014-06-06
  • 從基礎(chǔ)到高階探索Python中的文件操作

    從基礎(chǔ)到高階探索Python中的文件操作

    文件操作在Python編程中是不可或缺的一部分,在本篇博客中,我們將全面、深入地探討Python中的文件操作,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2023-06-06
  • 淘寶秒殺python腳本 掃碼登錄版

    淘寶秒殺python腳本 掃碼登錄版

    這篇文章主要為大家詳細介紹了淘寶秒殺python腳本,掃碼登錄版,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • Python腳本實現(xiàn)代碼行數(shù)統(tǒng)計代碼分享

    Python腳本實現(xiàn)代碼行數(shù)統(tǒng)計代碼分享

    這篇文章主要介紹了Python腳本實現(xiàn)代碼行數(shù)統(tǒng)計代碼分享,本文給出了實現(xiàn)代碼和使用方法及統(tǒng)計效果,需要的朋友可以參考下
    2015-03-03
  • Python操作SQLite/MySQL/LMDB數(shù)據(jù)庫的方法

    Python操作SQLite/MySQL/LMDB數(shù)據(jù)庫的方法

    這篇文章主要介紹了Python操作SQLite/MySQL/LMDB數(shù)據(jù)庫的方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • Python Pydantic進行數(shù)據(jù)驗證的方法詳解

    Python Pydantic進行數(shù)據(jù)驗證的方法詳解

    在 Python 中,有許多庫可用于數(shù)據(jù)驗證和處理,其中一個流行的選擇是 Pydantic,下面就跟隨小編一起學(xué)習(xí)一下Pydantic 的基本概念和用法吧
    2024-01-01
  • 詳解python學(xué)習(xí)筆記之解釋器

    詳解python學(xué)習(xí)筆記之解釋器

    這篇文章主要為大家詳細介紹了python學(xué)習(xí)筆記之解釋器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 如何使用Python逆向抓取APP數(shù)據(jù)

    如何使用Python逆向抓取APP數(shù)據(jù)

    今天給大伙分享一下 Python 爬蟲的教程,這次主要涉及到的是關(guān)于某 APP 的逆向分析并抓取數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • python利用lxml讀寫xml格式的文件

    python利用lxml讀寫xml格式的文件

    這篇文章主要為大家詳細介紹了python利用lxml讀寫xml格式的文件,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • python?tkinter實現(xiàn)彈窗的輸入輸出

    python?tkinter實現(xiàn)彈窗的輸入輸出

    這篇文章主要為大家詳細介紹了python?tkinter實現(xiàn)彈窗的輸入輸出,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評論