Python上下文管理器实现方法总结
目录
- 什么时候可以考虑上下文管理器
- 方法1(上下文管理器协议)
- 方法2(@contextmanager)
- 方法3(contextlib.closing())
什么时候可以考虑上下文管理器
当你的代码逻辑需要用到如下关键字时,可以考虑使用上下文管理器让你的代码更加优雅:
try:
...
finally:
...
接下来介绍实现上下文管理器的三种方法。
方法1(上下文管理器协议)
总所周知,open()是默认支持上下文管理器的。所以打开一个txt文件,并向里面写入内容,再关闭这个文件的代码可以这样写:
with open("1.txt", "w") as file:
file.write("this is a demo")
这是等同于:
file = None
try:
file = open("1.txt", "w")
file.write("this is a demo")
finally:
file.close()
要在Python中实现with语句的使用,就需要借助上下文管理器协议。也就是需要实现__enter__和__exit__两个魔法方法。
class OpenMyFile(object):
def __init__(self, path):
self.path = path
def __enter__(self):
print("opening the txt")
self.f = open(self.path, "w")
return self
def __exit__(self, *args, **kwargs):
print("closing the txt")
self.f.close()
def write(self, string):
print("writing...")
self.f.write(string)
with OpenMyFile("2.txt") as file:
file.write("this is a demo2")
# 输出:
opening the txt
writing...
closing the txt
同时能够看到本地生成了2.txt文件。需要注意的是,__enter__得return实例对象,不然会报异常:AttributeError: 'NoneType' object has no attribute 'write'
这是因为Python中的函数默认返回None。
方法2(@contextmanager)
利用contextlib中的contextmanager装饰器。
from contextlib import contextmanager
@contextmanager
def open_my_file(path):
print("opening the txt")
f = open("3.txt", "w")
yield f
print("closing the txt")
f.close()
with open_my_file("3.txt") as file:
file.write("this is demo3")
# 输出:
opening the txt
closing the txt
在@contextmanager装饰的函数中,需要用yield隔开两个逻辑语句。这里yield出来的对象会被as后面的变量接收。
方法3(contextlib.closing())
利用contextlib中的closing()方法。
from contextlib import closing
class OpenMyFile(object):
def __init__(self, path):
print("opening the txt")
self.f = open(path, "w")
def write(self, string):
self.f.write(string)
def close(self):
print("closing the txt")
self.f.close()
with closing(OpenMyFile("4.txt")) as file:
file.write("this is demo4")
# 输出:
opening the txt
closing the txt
与方法1不同。经过closing()方法包装过后,在with语句结束时,会强制调用对象的close()方法。所以使用方法3时,需要定义的方法不是__exit__()而是close()。
到此这篇关于Python上下文管理器实现方法总结的文章就介绍到这了,更多相关Python上下文管理器实现的三种方法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341