本来我们这个应该是和前面的with语句放在一块的,但是我想多写一篇,目的就是为了突出使用contextlib这个模块以后,我们的上下文管理器简化了很多。
我们还是先来看一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import contextlib
@contextlib.contextmanager def file_open(file_name): print("file open") # 此处代码就相当于之前的enter魔法函数实现的代码 yield {} # 必须是yield一个生成器,可以没有{},但是yield关键词必须有 print("file end") # 此处代码就相当于之前的exit魔法函数实现的代码
with file_open("envse.txt")as file_read: print("file is reading")
# 输出结果: file open file is reading file end
|
这是不是和我们前面的输出很相似,是的,这就是contextlib的好处,而且它可以把我们这个函数包装成一个上下文管理器对象,里面利用了我们生成器的一些特性。我们现在就是要搞清楚里面为什么是生成器,最好的方法就是直接阅读源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| def contextmanager(func): """@contextmanager decorator.
Typical usage:
@contextmanager def some_generator(<arguments>): <setup> try: yield <value> finally: <cleanup>
This makes this:
with some_generator(<arguments>) as <variable>: <body>
equivalent to this:
<setup> try: <variable> = <value> <body> finally: <cleanup> """
|
看到没有,这个函数的作用就是:
1 2
| with some_generator(<arguments>) as <variable>: <body>
|
所以我们刚才强调为什么必须是生成器的原因就在这里:some_generator
,所以没事可以多看源码,可以提高自身能力。
参考文章:浅谈 Python 的 with 语句