我正在尝试使用带有Python类的生成器,其工作方式与链接列表类似。
这是一个非常简单的例子:
class GeneratorTest():
def __init__(self, list):
if list:
self.elem = list[0]
if list[1:]:
self.n = GeneratorTest(list[1:])
else:
self.n = None
def __iter__(self):
return self
def next(self):
my_next = self
while my_next is not None:
yield my_next
my_next = my_next.n
当然这只是一个例子,但它足以说明这一点。
现在,我希望能够调用类似的东西:
g = GeneratorTest([1,2,3,4,5])
for x in g:
print x
当循环达到最后一个值时循环停止,但for循环只是无休止地继续。
我对发电机很新,所以我确信这是我在这里缺少的一个基本前提。
问题是否与我产生创建生成器的相同对象有关? 我敢肯定,如果我有一个包含GeneratorTest对象列表的对象,我可以非常简单地返回每个对象,但我觉得应该有一种方法可以让这个工作没有“包装”对象。
我在这里缺少什么?
答案 0 :(得分:4)
问题是next
(或者,在Py3中,__next__
)不应该是生成器 - 它应该在外部保持其状态,并且return
每个值。你每次都会继续返回一个新的生成器,但由于Python不会迭代那个生成器,所以你的循环实际上从未运行过。
这可能意味着您希望__iter__
最初返回self
以外的内容(尽管返回的内容需要有__iter__
返回self)。
但好消息是,生成器的存在恰恰是为了跟踪这些规则。将您当前的next
代码移到__iter__
,一切正常 - Python 迭代__iter__
返回(正如您所期望的那样)。
答案 1 :(得分:1)
当我从java移植treap数据结构时,我基本上做了这个;这段代码可以作为一个例子: http://stromberg.dnsalias.org/~strombrg/treap/
另请参阅“yield from”,这是一个最近的Python功能,使这更容易: http://www.python.org/dev/peps/pep-0380/
treap代码无需收益。