打开函数open的本质也是一个工厂函数,所以它的运行也是实例化的过程,产生的对象就是文件句柄
f = open("a.txt")
print(f.name)
f.close()
为了可以实现 with open 的结构,需要定义__enter__()、_ exit_()来实现上下文管理协议,以实现以下结构:
with open(“a.txt”) as f:
“代码块”
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print("执行enter")
def __exit__(selt, exc_type, exc_val, exc_tb): #__exit__()需要有四个参数
print("执行exit")
with Open("a.txt") as f:#使用with结构就会触发__enter__(self)结构
print("代码块")#在代码块执行完毕后会触发__exit__(self, exc_type, exc_val, exc_tb)
使用with结构就会触发__enter__(self)结构,为了可以实现as f的结构,需要return self。这样f = open.enter(f)就相当于实现了f = open(“a.txt”)
_ exit_()的三个参数 exc_type,、exc_val、 exc_tb 在with中的代码块没有报错的情况下都是None,会在所有代码块执行完毕后触发。但如果代码块中的内容触发异常则会在异常位置直接转入__exit__()并在__exit__()结束后直接结束with中内容的运行
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print("执行enter")
return self
def __exit__(selt, exc_type, exc_val, exc_tb):
print("执行exit")
with Open("a.txt") as f:
print(dsa)
print("dsa")#第二个print不会运行
_ exit_()可以定义返回值,当返回值是True时,exit()会吞掉异常,但依旧不会执行代码块中升起异常之后的代码
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print("执行enter")
def __exit__(selt, exc_type, exc_val, exc_tb):
print("执行exit")
return True
with Open("a.txt") as f:
print(dsa)
print("dsa")#依旧不会打印第二行,但不会报错
如果代码块中存在异常,则exit的三个参数分别为异常类型,异常语句,异常的追溯
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print("执行enter")
return self
def __exit__(selt, exc_type, exc_val, exc_tb):
print("执行exit")
print(exc_type,exc_val,exc_tb)
with Open("a.txt") as f:
print(f.name)
print(dsa)
类实现上下文管理协议的例子
class Foo:
def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary
def be_hit(self):
print("%s 正在挨揍" % self.name)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
return True
with Foo("Cjj", 18, 10000) as f:
f.be_hit()