摘要:上下文管理器協議包含和兩個方法。因此必要時在上下文管理器函數中使用語句防范錯誤。構建臨時忽略指定異常的上下文管理器。這是個基類,用于定義基于類的上下文管理器。塊結束時,按照后進先出的順序調用棧中各個上下文管理器的方法。
導語:本文章記錄了本人在學習Python基礎之控制流程篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。
本文重點:
1、掌握if語句之外的else的用法;一、if語句之外的else塊 1、else塊介紹
2、掌握上下文管理器的定義、協議、使用和with塊;
3、掌握有用的@contextmanger裝飾器。
if/else中if和else是同級對立的語句,對立是指流程經過一層if/else語句只能對應一種處理語句。而else在for/else,while/else,try/else語句中的功能則截然不同。后者中的else功能如下:
for/else:for循環沒有被break語句中止才運行else塊。
while/else:while循環沒有被break語句中止才運行else塊。
try/else:try塊中,沒有異常拋出時才運行else塊。
下面以for/else為例進行代碼實現:
for i in "apple": if i.isupper(): break else: raise ValueError("No upper string was found")2、try/else塊背后的編程風格
try/except不僅用于處理錯誤,還用于處理錯誤,這屬于EAFP編程風格。
EAFP:easier to ask for forgiveness than permission
取得原諒比獲得許可容易。即先假定存在有效的鍵或屬性,如果假定不成立,那么捕獲異常。
LBYL:look before you leap
三思而后行。即在調用函數或查找屬性或鍵之前顯式測試前提條件。
上下文管理器(context manger):在操作文件和建立數據庫連接的時候,我們最終需要關閉資源,這就是上下文管理器存在的意義。
上下文管理器協議:包含__enter__和__exit__兩個方法。
語法:try/finally模式和with語句
實例:try/finally模式
try: f = open("test.txt", "a+") f.write("Foo ") finally: f.close()
接下來我們用with語句進行替換:
實例:with語句
with open("test.txt", "a+") as f: f.write("Foo ")
分析:open 的返回值賦值給變量 f,當離開 with 代碼塊的時候,系統會自動調用 f.close() 方法。
總結:with塊的功能在于簡化try/finally模式。with語句在開始運行時會在上下文管理器對象上調用__enter__,而with語句結束時會調用__exit__方法。
Tips:with語句中的as語句是可選的,as語句將__enter__返回的值綁定到as語句后的變量。值得注意的是,對于open函數必須加上as字句來獲取文件的引用。
在掌握基本上下文管理器和with語句后,我們通過自定義上下文管理器來深刻認識with語句和__enter__以及__exit__的聯系。
實例:自定義滿足上下文管理器協議的類
class OpenFileDemo(object): def __init__(self, filename): self.filename = filename self.f = open(self.filename, "a+") return self.f def __exit__(self, exc_type, exc_value, traceback): self.f.close() if exc_type != SyntaxError: return True return False with OpenFileDemo("test.txt") as f: f.write("Foo ")3、異常處理
當上下文管理器遇到異常時由__exit__方法處理。傳給__exit__方法的三個參數如下:
exc_type:異常類(例如SyntaxError)。
exc_value:異常實例。有時會有參數傳給異常構造方法,例如錯誤信息,可以使用exc_value.args獲取這些參數。
traceback:traceback對象。
@contextmanger裝飾器是contextlib模塊中的工具,它可以將包含yield的語句變成上下文管理器。
其中,yield之前的語句在__enter__方法中執行,yield之后的語句在__exit__方法執行,yield后面的值是函數的返回值,綁定到實際調用的with中的as子句的目標變量上。
如此可以避免編寫一個類來實現上下文管理器協議。
實例:@contextmanger裝飾器應用之計時器
import contextlib import time @contextlib.contextmanager def timer(): start=time.time() yield end=time.time() usedtime=end-start print("Running time was %r seconds"%usedtime) with timer() as usedtime: time.sleep(1)
注意:一旦with塊在調用timer出現異常時,拋出的異常會在timer函數中的yield表達式中再次拋出。如果timer函數沒有處理異常的代碼就會導致函數運行中止,系統處于無效狀態。因此必要時在上下文管理器函數中使用try/finally語句防范錯誤。
@contextmanger集合了三個不同的Python特性:函數裝飾器、生成器和with語句,非常實用!
四、contextlib模塊中的實用工具最后說明contextlib模塊中包含的實用工具:
closing: 如果對象提供了 close() 方法,但沒有實現 _enter__/__exit_ 協議,那么可以使用這個函數構建上下文管理器。
suppress: 構建臨時忽略指定異常的上下文管理器。
@contextmanager: 這個裝飾器把簡單的生成器函數變成上下文管理器,這樣就不用創建類去實現管理器協議了。
ContextDecorator: 這是個基類,用于定義基于類的上下文管理器。這種上下文管理器也能用于裝飾函數,在受管理的上下文中運行整個函數。
ExitStack: 這個上下文管理器能進入多個上下文管理器。with 塊結束時,ExitStack 按照后進先出的順序調用棧中各個上下文管理器的_exit_ 方法。如果事先不知道 with 塊要進入多少個上下文管理器,可以使用這個類。例如,同時打開任意一個文件列表中的所有文件。
顯然,在這些實用工具中,使用最廣泛的是 @contextmanager 裝飾器,因此要格外留心。這個裝飾器也有迷惑人的一面,因為它與迭代無關,卻要使用 yield 語句。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44555.html
摘要:上下文管理器和塊上下文管理器協議包含和兩個方法。語句運行結束后,會在上下文管理器對象上調用方法,以此扮演子句的角色。 上下文管理器 最終,上下文管理器可能幾乎與子程序(subroutine)本身一樣重要。 在各種語言中 with 語句的作用不同,而且做的都是簡單的事,雖然可以避免不斷使用點號查找屬性,但是不會做事前準備和事后清理。 if語句之外的else塊 else太個性了, 其他語言...
摘要:導語本文章匯總了本人在學習基礎之緒論篇數據結構篇函數篇面向對象篇控制流程篇和元編程篇學習筆記的鏈接,打算入門的朋友們可以按需查看并交流。 導語:本文章匯總了本人在學習Python基礎之緒論篇、數據結構篇、函數篇、面向對象篇、控制流程篇和元編程篇學習筆記的鏈接,打算入門Python的朋友們可以按需查看并交流。 第一部分:緒論篇 1、Python數據模型 第二部分:數據結構篇 2、序列構成...
摘要:一個典型的上下文管理器類如下處理異常正如方法名明確告訴我們的,方法負責進入上下的準備工作,如果有需要可以返回一個值,這個值將會被賦值給中的。總結都是關于上下文管理器的內容,與協程關系不大。 Part 1 傳送門 David Beazley 的博客 PPT 下載地址 在 Part 1 我們已經介紹了生成器的定義和生成器的操作,現在讓我們開始使用生成器。Part 2 主要描述了如...
摘要:輔之以事件循環,協程可用于異步處理,尤其是在中。當前支持的協程基于增強型生成器,于版本開始采用。新的特性中,異步還有兩種新用途異步內容管理器和迭代器。 現在 Python 已經支持用協程進行異步處理。但最近有建議稱添加協程以全面完善 Python 的語言結構,而不是像現在這樣把他們作為生成器的一個類型。此外,兩個新的關鍵字———異步(async)和等待(await),都該添加到 Pyt...
閱讀 1201·2021-11-24 11:16
閱讀 3428·2021-11-15 11:38
閱讀 1920·2021-10-20 13:47
閱讀 546·2021-09-29 09:35
閱讀 2192·2021-09-22 15:17
閱讀 1013·2021-09-07 09:59
閱讀 3374·2019-08-30 13:21
閱讀 2904·2019-08-30 12:47