最终,上下文管理器可能几乎与子程序(subroutine)自己同样重要。python
在各类语言中 with 语句的做用不一样,并且作的都是简单的事,虽然能够避免不
断使用点号查找属性,可是不会作事前准备和过后清理。编程
else太个性了, 其余语言不一样用 不用这个多线程
取得原谅比得到许可容易(easier to ask for forgiveness than permission)。这是一
种常见的 Python 编程风格,先假定存在有效的键或属性,若是假定不成立,那么捕
获异常。这种风格简单明快,特色是代码中有不少 try 和 except 语句。与其余不少
语言同样(如 C 语言),这种风格的对立面是 LBYL 风格。
接下来,词汇表定义了 LBYL。app
三思然后行(look before you leap)。这种编程风格在调用函数或查找属性或键
以前显式测试前提条件。与 EAFP 风格相反,这种风格的特色是代码中有不少 if 语
句。在多线程环境中,LBYL 风格可能会在“检查”和“行事”的空当引入条件竞争。例
如,对 if key in mapping: return mapping[key] 这段代码来讲,若是在测试
以后,但在查找以前,另外一个线程从映射中删除了那个键,那么这段代码就会失败。
这个问题可使用锁或者 EAFP 风格解决。ide
上下文管理器协议包含 enter 和 exit 两个方法。with 语句开始运行时,会在上下文管理器对象上调用 enter 方法。函数
with 语句运行结束后,会在上下文管理器对象上调用 exit 方法,以此扮演 finally 子句的角色。测试
class LookingGlass: def __enter__(self): import sys self.original_write = sys.stdout.write sys.stdout.write = self.reverse_write return 'JABBERWOCKY' def reverse_write(self, text): self.original_write(text[::-1]) def __exit__(self, exc_type, exc_value, traceback): import sys sys.stdout.write = self.original_write if exc_type is ZeroDivisionError: print('Please DO NOT divide by zero!') return True
❻ 若是一切正常,Python 调用 exit 方法时传入的参数是 None, None, None;如
果抛出了异常,这三个参数是异常数据,以下所述。线程
解释器调用 enter 方法时,除了隐式的 self 以外,不会传入任何参数。传给
exit 方法的三个参数列举以下。code
exc_type
异常类(例如 ZeroDivisionError)。对象
exc_value
异常实例。有时会有参数传给异常构造方法,例如错误消息,这些参数可使用exc_value.args 获取。
traceback
traceback 对象。
能减小建立上下文管理器的样板代码量,由于不用编写一个完整的类,定义 enter 和 exit 方法,
而只需实现有一个 yield 语句的生成器,生成想让 enter 方法返回的值。
def __enter__(self): 通常返回 self本身
def __exit__(self, exc_type, exc_value, traceback):
exc_type
异常类(例如 ZeroDivisionError)。exc_value
异常实例。有时会有参数传给异常构造方法,例如错误消息,这些参数可使用exc_value.args 获取。traceback traceback 对象。