淺淡python中with的用法,上下文管理器


例子一

首先來看一段代碼:

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('正在執行')

 

上面代碼執行結果為:

實例化一個對象
進入
正在執行
退出

 

結論1

我們知道,實例化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('正在執行')

結果如下:

 把上面代碼中我們注釋掉的那一行代碼取消注釋,結果如下

 

 我們會發現,雖然我們故意在語句體中拋出一個錯誤,按照正常情況,執行到報錯地方就不會執行了,而__exit__是在語句體執行完之后執行的,但還是執行了__exit__方法;當我們在__exit__中給一個返回值為Ture時,就會忽略錯誤。

結論2

所有我們可以發現

with語句類似

  try :

  except:

  finally:

的功能:但是with語句更簡潔。而且更安全。代碼量更少。

   出現異常時,如果 __exit__ 返回 False(默認不寫返回值時,即為False),則會重新拋出異常,讓with 之外的語句邏輯來處理異常,這也是通用做法;如果返回 True,則忽略異常,不再對異常進行處理

例子三

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('正在執行')

把上面代碼中我們注釋掉的那一行代碼取消注釋,結果如下

 

結論

調用上下文管理器的 __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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM