Python3中with用法
? ? ? Python中的with語句用于用上下文管理器(context manager)定義的方法包裝塊的執行,它允許將常見的try…except…finally使用模式封裝起來以方便重用。
? ? ? 在Python中,在處理非托管資源(unmanaged resources)(如文件流)時使用with關鍵字。它允許確保你在使用資源的代碼完成運行時”清理”資源,即使拋出異常也是如此。它為try/finally塊提供”語法糖”(syntactic sugar)。
? ? ? with語句適用于對資源進行訪問的場合,確保不管使用過程中是否發生異常都會執行必要的”清理”操作,釋放資源,比如文件使用后自動關閉、線程中鎖的自動獲取和釋放等。
? ? ? 要在用戶定義的對象中使用with語句,你只需在對象方法中添加__enter__()和__exit__()方法。
? ? ? with語法:
with EXPRESSION [as TARGET]:SUITE
? ? ? with語句執行過程如下:
? ? ? (1).評估上下文表達式以獲得上下文管理器;
? ? ? (2).上下文管理器的__enter__()被加載以備后用;
? ? ? (3).上下文管理器的__exit__()被加載以備后用;
? ? ? (4).上下文管理器的__enter__()方法被調用;
? ? ? (5).如果TARGET包含在with語句中,則將__enter__()的返回值賦值給它。with語句保證如果__enter__()方法沒有錯誤返回,那么__exit__()將始終被調用。因此,如果在賦值給TARGET列表的過程中發生錯誤,它將被視為SUITE中發生的錯誤。__enter__()方法是可以帶返回值的,默認返回None。
? ? ? (6).SUITE被執行;
? ? ? (7).上下文管理器的__exit__()方法被調用。如果異常導致SUITE退出,則其類型、值和回溯(traceback)將作為參數傳遞給__exit__();否則,傳遞3個None。__exit__()方法也是可以帶返回值的,這個返回值應該是一個布爾類型True或False,默認為None(即False)。如果為False,異常會被拋出,用戶需要進行異常處理。如果為True,則表示忽略該異常。
? ? ? 如果SUITE因異常退出,并且__exit__()方法返回的值為False,則觸發異常。如果返回值為True,則異常被抑制,并繼續執行with語句之后的語句。
? ? ? 如果SUITE因異常以外的任何原因退出,則__exit__()的返回值將被忽略,并在所采取的退出類型的正常位置繼續執行。
? ? ? 以上內容主要翻譯于:https://docs.python.org/3/reference/compound_stmts.html#the-with-statement
? ? ? 以下為測試代碼:
class FileWriter(object):def __init__(self, file_name):print("run __init__")self.file_name = file_namedef __enter__(self):print("run __enter__")self.file = open(self.file_name, 'w')return self.filedef __exit__(self, type, value, traceback):print("run __exit__")print("type:", type); print("value:", value); print("traceback:", traceback)self.file.close()print("test FileWriter:")
with FileWriter('tmp.txt') as f:print("start write")f.write('hello world')print("end write")class ExceptionTest(object):def __enter__(self):print("run __enter__")return selfdef __exit__(self, type, value, traceback):print("run __exit__")print("type:", type); print("value:", value); print("traceback:", traceback)return False # return True # 注意返回True和False的區別:返回True則跳過異常,繼續執行with語句之后的語句def divide_by_0(self):v = 10/0print("\ntest ExceptionTest")
with ExceptionTest() as ex:ex.divide_by_0()print("test finish")
? ? ? 執行結果如下:
?
? ? ? GitHub:https://github.com/fengbingchun/Python_Test
總結
以上是生活随笔為你收集整理的Python3中with用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu上通过android too
- 下一篇: Python3中迭代器介绍