with的作用
我想大部分初学者第一次接触到with一定是在学习读取文件时。
with open(file_path) as f:
f.readlins()
当使用with时我们无需手动关闭资源。
但问题时为什么要with来关。
我们close不行吗。
f=open("output.txt","w+")
f.close()
异常和return的执行权限很高,可以忽略后面的逻辑直接结束函数。但是with的执行权限比它们还高,即使因为异常退出,它也依旧可以正常进行。with 是用来简化try /finally这种写法的。在我们学习自定义with之前。先来通过try/finally来体验一下什么叫执行权限很高。
def test():
try:
print('try...')
r = 10 / int('a')
print('result:', r)
except ValueError as e:
print("出现异常")
return
finally:
print('finally...')
test()
可以看到出现了异常,我们直接退出了函数,但finally依旧被执行了。 在finally里我们可以定义一些很重要的操作。即使异常也会照常进行。with和其作用差不多。
文件
为什么一定要关闭文件呢?
f=open("test","w")
f.write("aa")
s=open("test","r")
print(s.read())
可以看到写入操作没有生效,后续没有读到。
可以想象到会造成一些业务逻辑的混乱。所以一定要关闭文件
自定义with
当一个类中实现了__enter__和__exit__,那么就可以使用with语句。with会接管,必定执行__exit__里的逻辑
import sys
class reverse:
def __enter__(self):
global print
self.temp=print
print=self.myprint
def myprint(self,s):
sys.stdout.write(s[::-1])
def __exit__(self,type,value,traceback):
global print
print=self.temp
with reverse():
print("hello")
print("world")
print()
print("hello")
print("world")
可以看到我们进行了 一个很危险的操作。我们为print打了个补丁。这个操作必须改回来,否则你整个程序都将使用被打补丁的print。
当使用with时会运行__enter__离开with时会调用__exit__
如果我们自己调用。可能出现这种情况。
import sys
class reverse:
def __enter__(self):
global print
self.temp=print
print=self.myprint
def myprint(self,s):
sys.stdout.write(s[::-1])
def __exit__(self,type,value,traceback):
global print
print=self.temp
try:
re=reverse()
re.__enter__()
print(1)
re.__exit__(None,None,None)
except:
pass
print("ahhh")
因为异常 关闭语句无法运行。不想翻转输出的也翻转了