专栏首页中科院渣渣博肆僧一枚上下文管理协议(__enter__,__exit)

上下文管理协议(__enter__,__exit)

原文链接:https://www.cnblogs.com/Meanwey/p/9898673.html

一、上下文管理协议

即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

  1. __enter__()会在with语句出现(实例化对象)时执行
  2. __exit__()会在with语句的代码块实行完毕才会执行
class Open:
   def __init__(self,name):
          self.name = name
  
   def __enter__(self):                 #在实例化打开文件时即触发,在with时触发
         print('执行__enter__')
         return self                    #return的self会赋值给f,相当于通过Open类实例化处对象f

   def __exit__(self,exc_type,exc_val,exc_tb):    #在with中的代码块执行完毕才会触发
         print('执行__exit__')
 

with Open('a.txt') as f:                #会触发enter  '执行__enter__',相当于--》f=Open('a.txt').__enter__()
  print(f)                              #<__main__.Open object at 0x01477270>
  print(f.name)                         #'a.txt'
print('*'*10)                           #先---'执行__exit__'
                                        #后---'*********'   


Output:
---------------------------------------------
执行__enter__
<__main__.Open object at 0x000000000210B208>
a.txt
执行__exit__
**********
---------------------------------------------

二、__exit__

__exit__()中有三个参数分别代表异常类型,异常值和追溯信息,执行了__exit__则表示with语句执行完毕 1、若__exit__返回值不为True,则: a、若with语句中没有异常,则程序正常执行 b、若with语句中出现异常,则程序会执行到with中出错的语句并执行__exit__,然后程序终止,‘吐出’异常

class Open:
    def __init__(self,name):
        self.name = name
  
    def __enter__(self):                        
        print('执行__enter__')
        return self                    
  
    def __exit__(self,exc_type,exc_val,exc_tb):    
        print('执行__exit__')
        print(exc_type)                #<class 'AttributeError'>
        print(exc_val)                #'Open' object has no attribute 'age'
        print(exc_tb)                #<traceback object at 0x0178F738>
 
with Open('a.txt') as f:
     print(f)
     print(f.age)       
     #因为f对象没有age属性,则出现异常,程序执行到该句时将异常传递给__exit__的三个参数,并结束程序执行,报错
     print(f.name)        #该行语句后面的语句都不会执行,包括with语句的以外的语句也不会执行
print('*'*10) 


Output:
---------------------------------------------------------
执行__enter__
    print(f.age)
AttributeError: 'Open' object has no attribute 'age'
<__main__.Open object at 0x000000000257E4A8>
执行__exit__
<class 'AttributeError'>
'Open' object has no attribute 'age'
<traceback object at 0x0000000002583288>
---------------------------------------------------------

2、若__exit__返回值为True,则:  a、若with语句中没有异常,则程序正常执行  b、若with语句中出现异常,则程序会执行到with中出错的语句并执行__exit__,‘吞掉’异常。然后with语句中剩下的语句不会执行,但是会继续执行with语句以外的语句

class Open:
    def __init__(self,name):
        self.name = name
  
    def __enter__(self):                        
        print('执行__enter__')
        return self                    
  
    def __exit__(self,exc_type,exc_val,exc_tb):    
        print('执行__exit__')
        print(exc_type)                #<class 'AttributeError'>
        print(exc_val)                #'Open' object has no attribute 'age'
        print(exc_tb)                #<traceback object at 0x0178F738>
        return True
with Open('a.txt') as f:
     print(f)
     print(f.age)        #因为f对象没有age属性,则出现异常,程序执行到该句时将异常传递给__exit__的三个参数,并结束程序执行,'吞掉异常'不会报错
     print(f.name)       #该行语句后面的with中的语句都不会执行,但是with语句的以外的语句会继续执行
print('*'*10)            #'*********'

三、作用及好处:

  1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预   2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 自适应线性神经网络(Adaline)

    找不同:激活函数用阶跃函数换成了连续型函数,用一个Quantizer函数进行类别预测

    于小勇
  • Python的内置函数(三十一)、super()

    super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种...

    于小勇
  • torch.nn.Module

    上述几个属性中,_parameters、_modules和_buffers这三个字典中的键值,都可以通过self.key方式获得,效果等价于self._para...

    于小勇
  • Python 中的上下文管理

    当我们执行语句块前需要一些准备动作,在执行完成之后又需要执行一些收尾动作。比如:文件读写后需要关闭,数据库读写完毕后需要关闭连接,资源加锁解锁等情况。对于这种情...

    Ewdager
  • Python上下文管理器

      在Python中让自己创建的函数、类、对象支持with语句,就实现了上线文管理协议。我们经常使用with open(file, "a+") as f:这样的...

    用户1432189
  • python GUI库图形界面开发之PyQt5复选框控件QCheckBox详细使用方法与实例

    在这个例子中,将三个复选框添加到一个水平布局管理器中,并添加到一个QGroupBox组中

    砸漏
  • python实现文字版扫雷

    本文实例为大家分享了python实现文字版扫雷的具体代码,供大家参考,具体内容如下

    砸漏
  • 昨晚家里停网后,我写了一段代码破解了隔壁小姐姐的wifi密码...

    昨晚,家里停网了,对于码农而言,停网了,这能忍?打电话给修网络的,说太晚了,要第二天才能过来...

    良月柒
  • python with魔法语句

    这个是with默认封装的好的一个魔法盒子,封装了__enter__和__exit__两个函数:

    py3study
  • python 第3天

            msg = self.cooked_string + " "+msg + "."+str(self.cooked_level)

    py3study

扫码关注云+社区

领取腾讯云代金券