为了账号安全,请及时绑定邮箱和手机立即绑定

python-with语句

标签:
Python

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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消