递归数据结构的产量

时间:2012-06-25 15:42:43

标签: python

我正在尝试使用带有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对象列表的对象,我可以非常简单地返回每个对象,但我觉得应该有一种方法可以让这个工作没有“包装”对象。

我在这里缺少什么?

2 个答案:

答案 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代码无需收益。