我们中的许多人在我们的Python代码中一遍又一遍地看到这个片段:withopen('Hi.text','w')asf:f.write("Hello,there")然而,我们中的一些人不知道with是做什么用的,也不知道为什么我们需要在这里使用它。在本书中,您会发现几乎所有可以用.开始吧!首先,让我们考虑一下如果没有with关键字我们需要做什么。在这种情况下,我们需要先打开文件并尝试写入。成功或失败,我们最好在最后关闭它,所以我们的代码将如下所示:f=open('Hi.text','w')try:f.write('Hello,there')finally:f.close()那么,with关键字有什么用呢?它只是有助于将我们的try..finally代码缩短为单个with...语句!这是with语句的用法。那到底是什么呢?实际上,with语句本身在Python中并没有什么特别之处,它只是Python中上下文管理器的一个特性。引用自Python官方文档的上下文管理器是一种让您在需要时准确分配和释放资源的方法,或者简单地说:在对某些资源执行某些操作时缩短代码片段,这意味着您可以定义with语句的用法自己动手吧!我们如何做到这一点?好吧,这很简单,您只需要实现两个魔术函数:一个称为__enter__,另一个称为__exit__。第一种方法是编写一个实现这两个函数的类,如下所示:w')returnself.filedef__exit__(self,exc_type,exc_val,exc_trace_back):ifself.file:self.file.close()这里我们创建了一个普通的Python类,实现了两个魔术函数。注意这两个函数的签名:__enter__将只接受self,而__exit__将接受更多参数,示例中的三个是标准形式。这样我们就可以直接使用:withMy_file('hello.txt')asf:f.write('hello,world!')这里的with语句会先调用__init__构造一个新的对象,然后再调用__enter__方法;最后,它在代码块完成之前触发__exit__方法。所以,上面代码的近似等价物如下:myfile=My_file('hello.txt')f=myfile.__enter__()f.write('hello,world!')myfile.__exit(...)上下文管理器第二种方式是通过装饰器,如下所示:你从contextlib导入contextmanager你写一个函数来实现你想要的with语句。在函数上方添加一个装饰器@contextmanager。与你的函数一起使用!基于上面的介绍,我们来写一个装饰器上下文管理器吧!fromcontextlibimportcontextmanager@contextmanagerdefmy_file_open(fname):try:f=open(fname,'w')yieldf最后:print('Closingfile')f.close()withfile_open('hi.txt')asf:f.write('helloworld')上面几乎涵盖了with语句和上下文管理器的所有基础知识,但如果您想了解更多,请继续……!contextlib中有一些方便的工具供您使用。第一个是关闭。closing将基本上用您在退出前实现的另一个函数包装您的代码块。@contextmanagerdefclosing(f):try:f.write("写完")finally:f.close()withclosing(open("hi.text")):f.write("helloworld")比如,在上面的代码中,我们可以直接调用close(your_way_of_getting_resource),在你下面写的代码块即将完成之前(f.write("helloworld")),它会执行我们定义的try..finally块多于。另一种是使用抑制工具。我们知道,在很多情况下,如果我们尝试去获取一些资源,很有可能在打开文件时会出现FileNotFoundException等错误。在某些情况下,我们希望捕获错误或抑制它们,以便程序继续正常运行。抑制是我们可以抑制警告的一种方式。您需要做的就是弄清楚您要抑制哪个异常,然后使用suppress(your_choice_of_exception)编写,Python将从那里处理它。在其他情况下,您可能只想在输入with块时执行某些操作。在这种情况下,nullcontext将为您派上用场。nullcontext只会返回您在__enter__函数中定义的任何内容,不会执行任何其他操作。如果您在Python中处理异步操作以访问资源,则闭包是处理这种情况的实用程序。总结本文介绍了with语句的一些基本概念和用法,以及它的工作原理。还有很多有趣的东西,请查看Python的contextlib文档。最后,像往常一样快乐学习和快乐编码!
