PEP 288 – 生成器属性和异常
- 作者:
- Raymond Hettinger <python at rcn.com>
- 状态:
- 已撤回
- 类型:
- 标准跟踪
- 创建:
- 2002年3月21日
- Python 版本:
- 2.5
- 历史记录:
摘要
本 PEP 提出通过提供引发异常和与正在运行的生成器共享数据的机制来增强生成器。
状态
本 PEP 已撤回。异常引发机制已扩展并纳入PEP 343。属性传递功能从未得到广泛关注,没有明确的实现方式,并且没有提供一种干净的方法让正在运行的生成器访问其自己的命名空间。
基本原理
目前,只有基于类的迭代器可以提供属性和异常处理。但是,基于类的迭代器更难编写、更不紧凑、可读性更差且速度更慢。更好的解决方案是为生成器启用这些功能。
启用属性赋值允许将数据传递到正在运行的生成器并从中传递数据。使用属性共享数据的方法在 Python 中很普遍。其他方法也存在,但相比之下有点笨拙。
另一个发展步骤是添加一个生成器方法,允许将异常传递到生成器。目前,没有干净的方法从生成器外部触发异常。此外,生成器异常传递有助于缓解生成器对 try/finally 的禁止。对于需要在终止时刷新缓冲区或关闭资源的生成器来说,这种需求尤其迫切。
这两个提案都是向后兼容的,不需要任何新的关键字。建议将其用于 Python 2.5 版本。
生成器属性规范
本质上,该提案是为了模拟类的属性写入。唯一的问题是生成器缺乏一种引用自身实例的方法。因此,该提案是提供一个用于发现引用的函数。例如
def mygen(filename):
self = sys.get_generator()
myfile = open(filename)
for line in myfile:
if len(line) < 10:
continue
self.pos = myfile.tell()
yield line.upper()
g = mygen('sample.txt')
line1 = g.next()
print 'Position', g.pos
生成器属性的用途包括
- 为生成器客户端提供额外信息(如上所示)。
- 外部设置控制生成器操作的标志(可能告诉生成器何时介入或跳过数据组)。
- 编写具有复杂执行状态的惰性消费者(例如算术编码器输出流)。
- 编写协程(如 Mertz 博士的文章[1]中所示)。
此提案不会更改“yield”和“next”的控制流。唯一变化的是可以将数据传递到生成器并从中传递数据。大多数底层机制已经到位,只需要添加访问函数。
生成器异常传递规范
向生成器接口添加.throw(exception)
方法
def logger():
start = time.time()
log = []
try:
while True:
log.append(time.time() - start)
yield log[-1]
except WriteLog:
writelog(log)
g = logger()
for i in [10,20,40,80,160]:
testsuite(i)
g.next()
g.throw(WriteLog)
没有现有的解决方法可以在生成器内部触发异常。这是 Python 中唯一一种无法对活动代码进行异常处理或传递的情况。
生成器异常传递还有助于解决生成器的一个固有局限性,即禁止它们使用 try/finally 触发清理代码(PEP 255)。
注释 A:选择 throw 方法名称有几个原因。raise 是一个关键字,因此不能用作方法名称。与 raise 立即从当前执行点引发异常不同,throw 将首先返回到生成器,然后引发异常。单词 throw 暗示将异常放在另一个位置。throw 这个词在其他语言中已经与异常相关联。
考虑过其他方法名称:resolve()
、signal()
、genraise()
、raiseinto()
和flush()
。这些都不如throw()
合适。
注释 B:为了使throw()
语法简单,只支持 raise 语法的实例版本(不包含“raise string
”或“raise class, instance
”的变体)。
调用g.throw(instance)
相当于在最近的 yield 之后立即写入raise instance
。
参考文献
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0288.rst
上次修改时间:2023-09-09 17:39:29 GMT