阅读Python中一些新样式的视角,并转向发电机中从StopIteration
到return
的转变。我的主要问题是在自定义生成器中应该如何工作。我有一个课程,我直接介绍了__next__
方法,因为我必须添加一些逻辑来跟踪生成。
以下非常接近我的工作,具有所有关键元素。请注意,我实际上不仅仅是创建复制列表的生成器,而只是使其成为最小的示例。
class Test():
items = <list>
def __init__(self):
self.index = 0
def __next__(self):
if self.index >= len(self.items):
raise StopIteration
value = self.items[self.index]
self.index += 1
return value
def reset(self):
self.index = 0
因此,在这样的情况下,我要迭代列表,直到耗尽,然后下游呼叫将决定是重置发电机还是在耗尽后继续前进。但是,如何在不使用StopIteration
的情况下启用类似的东西,因为它被弃用了?在此处使用return
提出StopIteration
的标准建议似乎不适用,我真的宁愿不更改下游代码以检查产生Nones
那我应该在这里做什么?StopIteration
在__next__
中仍然可以接受吗?
StopIteration
是不是被弃用,您只是误解了一些生成器。您实际上没有发电机,您有一个迭代器。生成器只是使用yield
创建迭代器的功能。
您在不使用发电机的情况下创建自己的基础迭代器实现。迭代器完成后,迭代器从__next__
提出StopIterator
。您的代码在这里正确做到了。
来自python datamodel文档的发电机类型
Python的生成器提供了一种实现迭代器协议的方便方法。如果将容器对象的
。__iter__()
方法实现为生成器,则它将自动返回迭代器对象(从技术上讲,生成器对象(提供__iter__()
和__next__()
方法。有关发电机的更多信息,请参见收益表达式的文档中。
以及同一文档中的迭代类型部分:
iterator.__next__()
从容器中返回下一个项目。如果没有其他项目,请提高StopIteration
异常。
有一个弃用,但这仅涉及发电机功能中使用StopIteration
的问题。请参阅PEP 479-在发电机内部更改停止处理:
此PEP提出了对发电机的更改:当
。StopIteration
在发电机内升高时,将其替换为RuntimeError
。(更确切地说,当例外要冒出发电机的堆栈框架时,就会发生这种情况。(由于更改向后不兼容,因此最初使用__future__
语句引入该功能。
使用return
在发电机内部触发StopIteration
异常。手动升级StopIteration
实际上可以产生晦涩难懂的错误,因为所得迭代器的任何消费者都无法区分正确的使用异常和不正确的,偶然的 StopIteration
exc_26与生成器相关的例外。这使得很难调试,这就是为什么它们在生成器功能中使用在未来Python版本中的原因。
旁注:您的实现需要iterator.__iter__()
方法,该方法只需返回self
。
如果您想要可重置包装的生成器,一个可能的选项是将其数据保留在其他地方:
class Gen:
def __init__(self):
self.items = []
def restart(self):
for x in self.items:
yield x
g = Gen()
for x in g.restart():
pass
for x in g.restart():
pass