题
我试图理解 python 中的 with 语句。我到处都看到它谈论打开和关闭文件,并且旨在替换 try-finally 块。有人也可以发布一些其他例子吗?我只是在尝试 Flask,里面有大量的 with 语句。绝对要求有人提供一些澄清。
解决方案
有一个非常好的解释这里。基本上,with语句调用相关对象的两个特殊的方法。该__enter__和__exit__方法。该输入方法返回与“用”的语句关联的变量。虽然__exit__方法执行语句之后调用来处理任何清理(如关闭文件指针)。
其他提示
在with
语句的想法是要“做正确的事”阻力最小的路径。而文件实例是最简单的,穿线锁实际提供的非明显缺陷代码的更典型的例子:
try:
lock.acquire()
# do stuff
finally:
lock.release()
此代码被打破 - 如果锁定获取以往任何时候都失败了,要么有错误,会引发异常(因为代码将尝试释放它从未获得锁),或者更糟的是,如果这是一个递归锁,它将被提前释放。正确的代码看起来是这样的:
lock.acquire()
try:
# do stuff
finally:
# If lock.acquire() fails, this *doesn't* run
lock.release()
通过使用with
声明,就不可能得到这个错误的,因为它是建立在上下文管理器:
with lock: # The lock *knows* how to correctly handle acquisition and release
# do stuff
在其他地方,with
语句有助于大大类似于的功能和类装饰器的主要好处:它以“两件式”的代码,其可以由行代码的任意数量的分离(装饰函数定义在目前的情况下,try
块)并将其转化为“一体”的代码,其中程序员只需前面声明了什么,他们正在尝试做。
对于短的例子,这看起来并不像一个大的提升,但审查代码时,它实际上使一个巨大的差异。当我在一块的代码中看到lock.acquire()
,我需要向下滚动,并检查相应的lock.release()
。当我看到with lock:
,虽然,不需要这样的检验 - 我可以立即看到,锁将被正确释放
有十二个使用示例 with
在 PEP343, ,包括文件打开示例:
- 一个用于确保在块开始时在块开始时获得的锁的模板
- 一个用于打开文件的模板,该文件可确保在剩余块时关闭文件
- 用于提交或回滚数据库事务的模板
- 示例 1 不使用生成器重写
- 暂时重定向标准输出
- opens() 的变体也返回错误条件
- 另一个有用的例子是一个封锁信号的操作
- 此功能的另一个用途是十进制上下文
- 这是十进制模块的简单上下文管理器
- 通用的“对象关闭”上下文管理器
- 一个release()上下文,通过交换acquire()和release()调用来临时释放先前获取的锁
- 从左到右的“嵌套”上下文管理器自动筑巢的上下文以避免过多的凹痕
不隶属于 StackOverflow