1. 程式人生 > >python的with關鍵字

python的with關鍵字

前言

with表示式其實是try-finally的簡寫形式。但是又不是全相同。

格式

"""
格式
with context [as var]:
    pass
"""

其中的context是一個表示式,返回的是一個物件,var用來儲存context表示式返回的物件,可以有單個或者多個返回值。

with open('1.txt') as f:
    print(f.read())

print(f.closed)

表示式open(‘1.txt’)返回是一個_io.TextIOWrapper 型別的變數用f接受到。在with語句塊中就可以使用這個變數操作檔案。執行with這個結構之後。f會自動關閉。相當於自帶了一個finally。
image.png


但是with本身並沒有異常捕獲的功能,但是如果發生了執行時異常,它照樣可以關閉檔案釋放資源。

這個例子可以看出with沒有捕獲異常的功能。

with open('2.txt') as f:
    print(f.read())

print(f.closed)

image.png

這個例子可以看出with發生了異常也會關閉程式。

try:
    with open('1.txt') as f2:
        print(f2.read())
        f2.seek(-5,os.SEEK_SET)
except ValueError as e:
    print("error"
) print(f2.closed)

image.png

原理

"""
with 語句實質是上下文管理。
1、上下文管理協議。包含方法__enter__() 和 __exit__(),支援該協議物件要實現這兩個方法。
2、上下文管理器,定義執行with語句時要建立的執行時上下文,負責執行with語句塊上下文中的進入與退出操作。
3、進入上下文的時候執行__enter__方法,如果設定as var語句,var變數接受__enter__()方法返回值。
4、如果執行時發生了異常,就退出上下文管理器。呼叫管理器__exit__方法。
"""

自定義類

自定義類必須包含上述幾個方法才能正確使用with關鍵字。

class Mycontex(object):
    def __init__(self,name):
        self.name=name
    def __enter__(self):
        print("進入enter")
        return self
    def do_self(self):
        print(self.name)
    def __exit__(self,exc_type,exc_value,traceback):
        print("退出exit")
        print(exc_type,exc_value)
if __name__ == '__main__':
    with Mycontex('test') as mc:
        mc.do_self()

image.png

下面我們故意加一個NameError
image.png
即使程式發生了錯誤,python直譯器終止了我們的程式,但是我們的類 還是順利關閉了。

應用場景

1、檔案操作。2、程序執行緒之間互斥物件。3、支援上下文其他物件