Python Day 51 淺淡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('正在執行')


#上面代碼執行結果爲:
實例化一個對象
進入
正在執行
退出

#結論
咱們知道,實例化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
相關文章
相關標籤/搜索