with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
浅显得讲就是使用with语句,会自动帮我们在运行结束后进行清理,注意即使中途抛出异常,一样会进行清理,有点像unitest中 teardown的意思
举个最常见得例子:
####不使用with语句f=open("my.log","r")try: lines=f.readlines()except Exception as e: raise efinally: 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 <module> 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 <module> 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 enterNonei 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
作者:MR_Hanjc
链接:https://www.jianshu.com/p/6c57dcf746ed
共同学习,写下你的评论
评论加载中...
作者其他优质文章