理解Python的with语句

写过多线程程序的人确定对各类锁很熟悉,尤为是下面这种代码python

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,那么此异常就不会被再次抛出了编程语言

相关文章
相关标签/搜索