【1.135】__enter__和__exit__方法 上下文管理协议
上下文管理协议,即with语句,
为了让一个对象兼容with语句,
必须在这个对象的类中声明__enter__和__exit__方法
class Foo: def __init__(self,name): self.name = name def __enter__(self): print("出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量") return self def __exit__(self, exc_type, exc_val, exc_tb): print("with 中的语句执行完以后执行exit") with Foo("b.txt") as f1: print ("=======>") print(f1) print(f1.name) print("=======>") # 出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量 # =======> # <__main__.Foo object at 0x00000000022061D0> # b.txt # =======> # with 中的语句执行完以后执行exit
#b.txt文件与该文件 在同一个文件夹中
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,
with语句中代码块出现异常,则with后的 所有代码 都无法执行,
若果没有错误,那么这三个值就None
如果exit 返回值 为 true 那么:exit 中的异常获取三元素 就被忽略,
with模块 后面的语句照样执行,就当什么也没有发生
class Foo: def __init__(self,name): self.name = name def __enter__(self): print("出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量") return self def __exit__(self, exc_type, exc_val, exc_tb): print("with 中的语句执行完以后执行exit") print("错误类型",exc_type) print("错误值",exc_val) print("错误追踪信息",exc_tb) with Foo("b.txt") as f1: print ("=======>") print(f1) print(f1.name) raise AttributeError("WITH中出错了。。。。。") print("=======>") print("我就是来看热闹的,你没有错误我就出来") # 出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量 # =======> # <__main__.Foo object at 0x00000000021E61D0> # b.txt # with 中的语句执行完以后执行exit # 错误类型 <class 'AttributeError'> # 错误值 WITH中出错了。。。。。 # 错误追踪信息 <traceback object at 0x00000000021DE0C8>
若果没有错误,那么这三个值就None
class Foo: def __init__(self,name): self.name = name def __enter__(self): print("出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量") return self def __exit__(self, exc_type, exc_val, exc_tb): print("with 中的语句执行完以后执行exit") print("错误类型",exc_type) print("错误值",exc_val) print("错误追踪信息",exc_tb) with Foo("b.txt") as f1: print ("=======>") print(f1) print(f1.name) # raise AttributeError("WITH中出错了。。。。。") print("=======>") print("我就是来看热闹的,你没有错误我就出来") # 出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量 # =======> # <__main__.Foo object at 0x00000000023E61D0> # b.txt # =======> # with 中的语句执行完以后执行exit # 错误类型 None # 错误值 None # 错误追踪信息 None # 我就是来看热闹的,你没有错误我就出来
如果exit 返回值 为 true 那么:exit 中的异常获取三元素 就被忽略,
with模块,后面的语句照样执行,就当什么也没有发生
class Foo: def __init__(self,name): self.name = name def __enter__(self): print("出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量") return self def __exit__(self, exc_type, exc_val, exc_tb): print("with 中的语句执行完以后执行exit") print("错误类型",exc_type) print("错误值",exc_val) print("错误追踪信息",exc_tb) return True with Foo("b.txt") as f1: print ("=======>") print(f1) print(f1.name) raise AttributeError("WITH中出错了。。。。。") print("=======>") print("我就是来看热闹的,你没有错误我就出来") # 出现with语句,对象的__enter__被触发,有返回值,就赋值给 as 后声明的变量 # =======> # <__main__.Foo object at 0x0000000001E86198> # b.txt # with 中的语句执行完以后执行exit # 错误类型 <class 'AttributeError'> # 错误值 WITH中出错了。。。。。 # 错误追踪信息 <traceback object at 0x0000000001E7AF48> # 我就是来看热闹的,你没有错误我就出来
看看 如何模拟 with 语句打开 open,利用上下文管理协议
用途或者说好处:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,
可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
class Open: def __init__(self,file,mode="r",encoding="UTF-8"): self.file = file self.mode = mode self.enconding = encoding def __enter__(self): self.f=open(self.file,mode=self.mode,encoding=self.enconding) #如果没有定义,默认就open中的功能 return self.f def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() return True def __getattr__(self, item): #定义了读 print(item) return getattr(self.f,item) with Open("b.txt","w+",encoding="utf-8") as f1: print(f1) f1.write("--231--dasfdfa----") # 只定义了读,其他就用open默认定义的功能 # f1.sdfadfa #抛出错误,交给exit来处理,如果运行这句,那下面所有代码都不能运行 f1.seek(0) # 只定义了读,其他就用open默认定义的功能 a=f1.read(3) # 使用了定义的读 getattr print(a)
浙公网安备 33010602011771号