6

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

我在这里想念什么?

4

2 回答 2

4

问题是next(或者,在 Py3 中,__next__)不应该是一个生成器——它应该在外部维护它的状态,以及return每个值。你的每次都会返回一个新的生成器,但由于 Python 不会迭代那个生成器,你的循环永远不会真正运行。这可能意味着您想要__iter__返回不同于self最初的东西(尽管它返回的任何东西都需要有一个__iter__返回自我的东西)。

但好消息是生成器的存在正是为了为您跟踪这些规则。将您当前的next代码移入__iter__并且一切正常 - Python确实会迭代任何__iter__返回(如您所料)。

于 2012-06-25T15:50:54.850 回答
1

当我从 java 移植一个 treap 数据结构时,我基本上是这样做的;此代码可以作为示例: http ://stromberg.dnsalias.org/~strombrg/treap/

另请参阅“yield from”,这是一个使这更容易的最新 Python 功能:http: //www.python.org/dev/peps/pep-0380/

treap 代码在没有 yield from 的情况下执行此操作。

于 2012-06-25T16:03:27.853 回答