Python的with語句


 

寫過多線程程序的人肯定對各種鎖很熟悉,尤其是下面這種代碼

def lock_usage:
    lock.Lock()
    if(...) :
        lock.Unlock()
    return

    lock.Unlock()
    return

為了避免造成死鎖,需要在每個return語句之前都釋放鎖。像上面的代碼中,如果代碼的執行路徑很多,代碼中就會包含大量的unlock語句,代碼混亂還是小事兒,如果萬一忘掉了unlock,就是個潛在的危險。除了鎖之外,包括文件描述符的關閉等涉及到資源釋放的操作都會有這種問題。
為了解決內存泄漏的內存問題,現代的編程語言提供了垃圾回收機制。同樣為了解決上面這種有限資源的釋放問題,很多語言都提供了一些語法特性。Python有with語句,C#有using,Go有defer。

先看解決這種問題的常規做法,使用finally

try:
    lock.Lock()
    ......
except:
    prcess_except()
finally:
    lock.Unlock

這么寫使得代碼很亂,尤其是當......處的代碼也包含有類似代碼時,會使得代碼更加混亂。再來看使用with語句后的代碼

class LockContext(object):
    __init__(self, lock):
    self.lock = lock

    __enter__(self):
        self.Lock()

    __exit__(self, type, value, traceback):
        if type != None:
            process_except()
        self.Unlock()
        return false

with LockContext(lock) as lock:
    .......

這樣寫出來,代碼量雖然差不多,但是結構清晰了很多。在上面的代碼中__init__中的賦值是可選的,只要保證能夠訪問到所需的變量就可。

Python中的with語句中要求對象實現__enter__和__exit__函數。調用with語句時,會先分析該語句,執行__enter__函數,然后在當前suite退出時,會調用__exit__函數。__exit__函數中除了可以做釋放資源的操作之外,同時也是異常處理的地方。如果當前suite正常退出,沒有拋出任何異常,__exit__的幾個參數均為None。否則,則將此異常的type、value、traceback作為參數傳遞給__exit__函數,同時,如果__exit__返回false,此異常會再次拋出,上一級代碼suite可以繼續處理,如果__exit__返回true,那么此異常就不會被再次拋出了


免責聲明!

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



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