I used to work for the government. Now I work for the public.

Python 上下文管理器

咋一听上下文管理器,可能会比较陌生,但是我相信你看了下面的代码后,就能理解

什么是上下文管理器?

Python 当中典型的上下文管理器,是由 with ... as ... 这样的语法构成的,比如我们常用的打开文件。

with open ('file.txt','r') as f:
    f.read()

我们知道打开一个文件除了可以用 with 关键字包裹以外还可以用普通的方式打开

f = open('file.txt','r')
lines = f.read()
f.close()

对比两者发现,都有 open('file.txt','r') 语句,是的没错,这个语句是必须的。而且第 2 种方式还多了一个 f.close() 方法,这个方法实际上是用来关闭文件句柄的,有的书中称为文件流。使用完后,关闭文件句柄是一个好习惯,不然文件一直被 hold 住,很可能导致其他程序也用不了这个文件。但是有时候我们会忘记关闭,或者是忘记一些扫尾工作。

作用是什么呢?

从上面就可以知道,上下文管理器的作用就是可以帮助我们执行一些扫尾工作,比如关闭文件句柄,关闭数据库连接等等,具体是什么功能,是由我们自己决定的,这个就是接下来要讲的。

如何实现上下文管理器?

class Test(object):
    def __init__(self,args):
        self.args = args
        pass

    def __enter__(self):
        print('这是with开始')
        return self.args

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('这是with结束')

with Test(args='value') as t:
    print(t)

上面就是一个典型的实现呢,我们定义了一个 class 然后类中有两个双下划线方法 __enter____exit__,这个两个方法就是实现上下文管理器的重点。在我们使用 with ... as ... 的时候,__enter__ 会把返回值,通过 as 传递给后面的接受者,在我们的例子中也就是 t ,相当于就是把 self.args 赋值给了 t 然后输出的就是 value,而 __exit__ 的作用就是在 with ... as ... 代码块执行完毕之后,再执行我们想要的内容,我这里因为没有打开文件,也没有连接数据库,所以就简单的输出。


第二种方式实现上下文管理器

from contextlib import contextmanager

@contextmanager
def session(args):  
    connect = Connect(args)
    yield connect
    connect.close()

with session as s:
    s.query("select * from user")

第二种方式是使用 contextmanager 装饰器,被装饰的对象可以是一个普通的函数,而不需要第一种方法的实现必须是一个对象。被装饰的函数有一个要求,即需要通过 yield 关键字生成一个对象,生成的对象,在我们使用的使用,会被 as 关键字传递接受,然后 yield 后面的代码会在 with ... as ... 执行完毕后自动执行,上面的例子就是会自动执行 connect.close()

总结

Python 中还有很多挺神奇的用法,个人精力有限,欢迎各位投稿 👏👏👏

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注