1. 程式人生 > >with as 如何工作

with as 如何工作

簡練 ret 被調用 file recent 異常拋出 day cal pan

with如何工作?

Python對with的處理還是很機智滴.基本思想就是with所求值的對象必須有一個__enter__()方法,一個__exit__()方法

緊跟with後面的語句被求值後,返回對象的__enter__()方法被調用,這個方法的返回值將被賦值給as後面的變量,當with後面的代碼塊全部被執行完之後,將調用前面返回對象的__exit__()方法.

下面例子可以具體說明with如何工作

class Sample:
    def __enter__(self):
        print("in __enter__")
        return "foo"  # 返回值賦值給了"sample",所以下面代碼打印的foo
def __exit__(self, exc_type, exc_val, exc_tb): print("in __exit__()") def get_sample(): return Sample() with get_sample() as sample: print("sample", sample)

運行代碼,輸出如下

in __enter__
sample foo
in __exit__()

1,__enter__()方法被執行

2,__enter__()方法返回的值 - 這個例子中的"foo",賦值給變量"sample"

3,執行代碼塊,打印變量"smple"的值為"foo"

4,__exit__()方法被調用

with真正強大之處是他可以處理異常,可能你已經註意到Sample類的__exit__方法有三個參數

exc_type,exc_val,exc_tb.這些參數在異常處理中相當有用,我們開修改下代碼:

class Sample:
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("type: ", exc_type)
        print("value: ", exc_val)
        
print("trace: ", exc_tb) def do_something(self): bar = 1/0 return bar + 10 with Sample() as sample: sample.do_something()

這個例子中,wilt後面的get_sample()變成了Sample().這沒有任何關系.只要緊跟with後面的語句所返回的對象有__enter__()和__exit__()方法即可,此例中,Sample()的__enter__()方法返回新創建的Sample對象,並賦值給變量sample.

代碼執行後:

type:  <class ZeroDivisionError>
value:  division by zero
trace:  <traceback object at 0x00000192D8305108>
Traceback (most recent call last):
  File "D:/數據管理/python全棧開發13期/網絡編程/day_39/隊列.py", line 164, in <module>
    sample.do_something()
  File "D:/數據管理/python全棧開發13期/網絡編程/day_39/隊列.py", line 160, in do_something
    bar = 1/0
ZeroDivisionError: division by zero

實際上,在with後面的代碼塊拋出任何異常時,__exit__()方法被執行.正如例子所示,異常拋出時,與之關聯的type,value和trace傳給__exit__()方法,因此判處的ZeroDivisionError異常被打印出來了.開發庫,清理資源,關閉文件等等操作,都可以放在__exit__()方法當中.

因此,Python的with語句時提供了一個有效的機制,讓代碼更簡練,同時在異常產生時,清理工作更簡單.

with as 如何工作