日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python with方法

發(fā)布時間:2024/9/30 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python with方法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

閱讀目錄

在實際的編碼過程中,有時有一些任務(wù),需要事先做一些設(shè)置,事后做一些清理,這時就需要python with出場了,with能夠?qū)@樣的需求進行一個比較優(yōu)雅的處理,最常用的例子就是對訪問文件的處理。

一般訪問文件資源時我們會這樣處理:

-------------------------------------------------------------------- 注:如果你對python感興趣,我這有個學(xué)習(xí)Python基地,里面有很多學(xué)習(xí)資料,感興趣的+Q群:895817687 --------------------------------------------------------------------f = open(r'c:\test.txt', 'r') data = f.read() f.close()

這樣寫沒有錯,但是容易犯兩個毛病:

  • 如果在讀寫時出現(xiàn)異常而忘了異常處理。
  • 忘了關(guān)閉文件句柄
  • 以下的加強版本的寫法:

    f = open(r'c:\test.txt', 'r')try:data = f.read()finally:f.close()

    以上的寫法就可以避免因讀取文件時異常的發(fā)生而沒有關(guān)閉問題的處理了。代碼長了一些。
    但使用with有更優(yōu)雅的寫法:

    with open(r'c:\test.txt', 'r') as f:data = f.read()

    說明:
    with后面接的對象返回的結(jié)果賦值給f。此例當(dāng)中open函數(shù)返回的文件對象賦值給了f.with會自已獲取上下文件的異常信息。
    with是如何做到的呢?
    with后面返回的對象要求必須兩__enter__()/exit()這兩個方法,而文件對象f剛好是有這兩個方法的,故應(yīng)用自如。
    pytho中官方定義說明如下(https://docs.python.org/2/reference/datamodel.html#context-managers):

    object.__enter__(self) 進入與此對象相關(guān)的運行時上下文。with語句將將此方法的返回值綁定到語句的AS子句中指定的目標(如果有設(shè)置的話)object.__exit__(self, exc_type, exc_value, traceback) 退出與此對象相關(guān)的運行時上下文。參數(shù)描述導(dǎo)致上下文退出的異常。如果上下文運行時沒有異常發(fā)生,那么三個參數(shù)都將置為None。 如果有異常發(fā)生,并且該方法希望抑制異常(即阻止它被傳播),則它應(yīng)該返回True。否則,異常將在退出該方法時正常處理。請注意, __exit__()方法不應(yīng)該重新拋出傳入的異常,這是調(diào)用者的職責(zé)。

    所謂上下文管理協(xié)議,就是咱們打開文件時常用的一種方法:with

    enter(self):當(dāng)with開始運行的時候觸發(fā)此方法的運行

    exit(self, exc_type, exc_val, exc_tb):當(dāng)with運行結(jié)束之后觸發(fā)此方法的運行

    exc_type如果拋出異常,這里獲取異常的類型

    exc_val如果拋出異常,這里顯示異常內(nèi)容

    exc_tb如果拋出異常,這里顯示所在位置

    下面舉例說明他的原理:

  • 無異常發(fā)生時的例子:
  • #!/user/bin/env python3 #-*- coding:utf-8 -*-class Test:def __enter__(self):print('__enter__() is call!')return selfdef dosomething(self):print('dosomethong!')def __exit__(self, exc_type, exc_value, traceback):print('__exit__() is call!')print(f'type:{exc_type}')print(f'value:{exc_value}')print(f'trace:{traceback}')print('__exit()__ is call!')with Test() as sample:sample.dosomething()>> __enter__() is call! dosomethong! __exit__() is call! type:None value:None trace:None __exit()__ is call!

    以上的實例Text,我們注意到他帶有__enter__()/exit()這兩個方法,當(dāng)對象被實例化時,就會主動調(diào)用__enter__()方法,任務(wù)執(zhí)行完成后就會調(diào)用__exit__()方法,另外,注意到,exit()方法是帶有三個參數(shù)的(exc_type, exc_value, traceback), 依據(jù)上面的官方說明:如果上下文運行時沒有異常發(fā)生,那么三個參數(shù)都將置為None, 這里三個參數(shù)由于沒有發(fā)生異常,的確是置為了None, 與預(yù)期一致.

  • 有異常發(fā)生時,會拋出異常的例子:
    以下例子在上面稍做了一些修改,讓運行時產(chǎn)生異常,看看這三個參數(shù)的賦值情況:
  • #!/user/bin/env python3 #-*- coding:utf-8 -*-class Test:def __enter__(self):print('__enter__() is call!')return selfdef dosomething(self):x = 1/0print('dosomethong!')def __exit__(self, exc_type, exc_value, traceback):print('__exit__() is call!')print(f'type:{exc_type}')print(f'value:{exc_value}')print(f'trace:{traceback}')print('__exit()__ is call!')# return Truewith Test() as sample:sample.dosomething() >> __enter__() is call! Traceback (most recent call last): __exit__() is call! type:<class 'ZeroDivisionError'>File "C:/Users/xxx/PycharmProjects/Test1/test.py", line 23, in <module> value:division by zerosample.dosomething() trace:<traceback object at 0x000001C08CF32F88>File "C:/Users/xxx/PycharmProjects/Test1/test.py", line 10, in dosomething __exit()__ is call!x = 1/0 ZeroDivisionError: division by zero

    從結(jié)果可以看出, 在執(zhí)行到dosomethong時就發(fā)生了異常,然后將異常傳給了__exit__(), 依據(jù)上面的官方說明:如果有異常發(fā)生,并且該方法希望抑制異常(即阻止它被傳播),則它應(yīng)該返回True。否則,異常將在退出該方法時正常處理。當(dāng)前__exit__并沒有寫明返回True,故會拋出異常,也是合理的,但是正常來講,程序應(yīng)該是不希望它拋出異常的,這也是調(diào)用者的職責(zé),我們將再次修改__exit__, 將其返回設(shè)置為True,

  • 有異常發(fā)生時,不再拋出異常的例子:
  • # 在上面的例子上做點修改. #!/user/bin/env python3 #-*- coding:utf-8 -*-class Test:def __enter__(self):print('__enter__() is call!')return selfdef dosomething(self):x = 1/0print('dosomethong!')def __exit__(self, exc_type, exc_value, traceback):print('__exit__() is call!')print(f'type:{exc_type}')print(f'value:{exc_value}')print(f'trace:{traceback}')print('__exit()__ is call!')return Truewith Test() as sample:sample.dosomething()>> __enter__() is call! __exit__() is call! type:<class 'ZeroDivisionError'> value:division by zero trace:<traceback object at 0x000001C94E592F88> __exit()__ is call!

    從結(jié)果看,異常拋出被抑制了,符合預(yù)期。

    總結(jié)

    以上是生活随笔為你收集整理的python with方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。