python中with的实现原理
一般上,打开文件是
def open_file1()
f = open("output.txt", "w")
try:
f.write("write successfully")
except Exception as e:
print(e)
finally:
f.close()
这个代码块默认打开output.txt文件,如果出现异常就会调用except;最终无论是否出现异常都会调用 finally 里面的 f.close()代码。
def open_file2()
with open("output.txt", "w") as f:
f.write("write successfully")
这块代码可以实现的功能,和函数open_file1()实现的功能是一样的;我们可以明显的看出这块代码更为简洁。
上下文管理器
任何实现了 __enter__和__exit__方法的对象都可以称之为上下文管理器,上下文管理器对象可以使用with关键字。显然,上述的函数open_file2()使用了上下文管理器。
class defined_open_file():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
print("打开文件")
self.file = open(self.filename, self.mode)
return self.file;
def __exit__(self, *args):
print("关闭文件")
self.file.close();
def open_file3():
with defined_open_file("output.txt", "w") as f:
f.write("write successfully")
open_file1(),open_file2(),open_file3()这三个函数,实现的功能是一样的,其中open_file2()和open_file3()实现的原理是一样的,在第三块代码中我们
Python此外还提供了contextmanager这个装饰器,进一步的简化了上下文管理器的实现方式。通过yield将函数分割成两部分,yield之前的语句是在__enter__方法中执行的,yield之后的语句在__exit__方法中执行,紧跟yield后面的值是__enter__方法返回的值。
from contextlib import contextmanager
@contextmanager
def file_open(path, mode):
f = open(path, mode)
yield f
f.close()
# 调用
with file_open("output.txt", "w") as f:
# 此时调用关键字yield之前的代码,并将yield关键字之后的参数赋予as关键字之后的参数
f.write("write successfully")
# 在with结束或出现异常的时候,再调用yield之后的代码
Python提供了with语法用于简化资源操作的后续清楚操作,是try/finally的代替方法,实现原理建立在上下文管理器之上。此外,python还提供了一个contextmanager装饰器,更进一步简化上下文管理器的实现方式。