python-with语句

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

浅显得讲就是使用with语句,会自动帮我们在运行结束后进行清理,注意即使中途抛出异常,一样会进行清理,有点像unitest中 teardown的意思

举个最常见得例子:

####不使用with语句
f=open("my.log","r")
try:
    lines=f.readlines()
except Exception as e:
    raise e
finally:
    f.close()
####使用with语句
with open("my.log","r") as f:
    lines=f.readlines()

如果不适用with语句需要在我们不使用文件得时候手动去关闭文件,而with则不用,会自动帮我们处理,不管运行成功或者失败

通过例子我们可以大致看出来with语句得语法格式

with context_expression [as  something]:
       with-body

需要注意with语句操作得对象必须具有上下文管理器,也就是需要具有__ enter__方法,__ exit__方法

__enter __:入口方法,运行在with-body之前
__exit __:退出清理方法,运行在with-body之后

刚刚得例子虽然能说明问题,但是看得不够直观,我们来创建一个具有上下文管理器得对象

class my():
    def __enter__(self):
        print("i am enter")
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("i am exit")
with my() as haha:
    print("i am with body")
###输出
i am enter
i am with body
i am exit

上面得例子可以看出所有得运行过程,但是并没有体现出在with body中出错后会运行exit方法,来看下面得例子:

class my():
    def __enter__(self):
        print("i am enter")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("i am exit")
with my() as haha:
    print("i am with body"+1)
###输出
i am enter
Traceback (most recent call last):
  File "/Users/hjc/workspace/myutils/meiyouyong.py", line 8, in 
i am exit
    print("i am with body"+1)
TypeError: must be str, not int
i am exit

可以看到exit方法被执行了,但是这里有个bug,如果我们给my类加个成员方法,这时haha找不到该方法

class my():
    def __enter__(self):
        print("i am enter")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("i am exit")
    def run(self):
        print("i am run")
with my() as haha:
    haha.run()
###运行结果
i am enter
Traceback (most recent call last):
  File "/Users/hjc/workspace/myutils/meiyouyong.py", line 10, in 
    haha.run()
AttributeError: 'NoneType' object has no attribute 'run'
i am exit

上面得例子很明显haha并没有run方法,这是为什么呢,我们再看一下下面得例子

class my():
    def __enter__(self):
        print("i am enter")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("i am exit")
    def run(self):
        print("i am run")
with my() as haha:
    my().run()
###运行结果
i am enter
i am run
i am exit

我们把haha改成了my()就可以了,为什么haha作为my()得替代没有呢,原因是my()先运行得是enter方法,而enter并没有返回值,导致haha替代my()时为None,自然没有run()方法

class my():
    def __enter__(self):
        print("i am enter")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("i am exit")
    def run(self):
        print("i am run")
with my() as haha:
    print(haha)
###运行结果
i am enter
None
i am exit

找到问题得原因就简单了,我们只要运行enter时候把对象返回就好了

class my():
    def __enter__(self):
        print("i am enter")
        return self    #将对象返回
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("i am exit")
    def run(self):
        print("i am run")
with my() as haha:
    haha.run()
###运行结果
i am enter
i am run
i am exit

ok,到这里就结束了

你可能感兴趣的:(python-with语句)