#案例一安全
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('正在執行') #上面代碼執行結果爲: 實例化一個對象 進入 正在執行 退出 #結論 咱們知道,實例化Foo,獲得obj對象,會執行Foo的__init__方法,也就是打印了第一句; 按照,程序從上至下執行,應該會打印「正在執行」纔對,爲何會在它以前先打印了進入,在它以後打印了退出呢? 由於咱們在定義Foo時,定義了__enter__和__exit__方法,那麼咱們實例化的對象obj就是一個上下文管理器, 即含有__enter__和__exit__方法的對象就是上下文管理器。 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('退出') # return True obj = Foo() with obj: raise ImportError print('正在執行')
#結果以下spa
#把上面代碼中咱們註釋掉的那一行代碼取消註釋,結果以下code
咱們會發現,雖然咱們故意在語句體中拋出一個錯誤,按照正常狀況,執行到報錯地方就不會執行了,而__exit__是在語句體執行完以後執行的,但仍是執行了__exit__方法;當咱們在__exit__中給一個返回值爲Ture時,就會忽略錯誤。對象
#結論blog
#結論 全部咱們能夠發現 with語句相似 try : except: finally: 的功能:可是with語句更簡潔。並且更安全。代碼量更少。 出現異常時,若是 __exit__ 返回 False(默認不寫返回值時,即爲False),則會從新拋出異常,讓with 以外的語句邏輯來處理異常,這也是通用作法;若是返回 True,則忽略異常,再也不對異常進行處理
##案例三ci
class Foo(object): def __init__(self): print('實例化一個對象') def __enter__(self): print('進入') # return self def __exit__(self, exc_type, exc_val, exc_tb): print('退出') with Foo() as obj: print(obj,type(obj)) print('正在執行')
#結果get
#把上面代碼中咱們註釋掉的那一行代碼取消註釋,結果以下it
#結論io
調用上下文管理器的 __enter__ 方法時;若是使用了 as 子句,則將 __enter__() 方法的返回值賦值給 as 子句中的目標 with 上下文管理器 as target: 代碼語句體 with後面必須跟一個上下文管理器,若是使用了as,則是把上下文管理器的 __enter__() 方法的返回值賦值給 target,target 能夠是單個變量,或者由「()」括起來的元組(不能是僅僅由「,」分隔的變量列表,必須加「()」)
##案例四
咱們常常會看到這樣的代碼: with open("/tmp/foo.txt") as file: data = file.read()
#結論
這裏使用了 with 語句,無論在處理文件過程當中是否發生異常,都能保證 with 語句執行完畢後已經關閉了打開的文件句柄。若是使用傳統的 try/finally 範式,則要使用相似以下代碼: somefile = open(r'somefileName') try: for line in somefile: print line # ...more code finally: somefile.close() 比較起來,使用 with 語句能夠減小編碼量。已經加入對上下文管理協議支持的還有模塊 threading、decimal 等。
#補充
with只能配合上下文管理器使用,常見的上下文管理器有:
file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore