如何在没有下一个迭代的情况下迭代迭代对象?

时间:2017-10-02 19:50:51

标签: python iterator

我已就此主题的类似问题进行过研究,但没有发现重复。

如果对象实现__iter__协议,则说明对象是 iterable

  

iterator.__iter__():   返回迭代器对象本身。这是允许容器和迭代器与for和in语句一起使用所必需的。

     

iterator.__next__():   从容器中返回下一个项目。如果没有其他项目,请提高StopIteration例外。

根据我的理解,这适用于所有迭代器对象。我遇到过一个实现二叉树容器的代码。容器只有__iter__,节点对象也驻留在其中。

Node对象的__iter__实现返回生成器。它产生了对象,似乎做了所有逻辑,没有__next__的实现。

此代码的实际工作原理如何?它似乎只是作为常规迭代器运行,但是这个没有__next__。当然,如果我手动执行iter(obj)然后next(obj)它就可以了。以下是代码段:

class BinaryCont(object):

    def __init__(self):
        self.root = None
        self.size = 0

    def __iter__(self):

        class EmptyIter():
            def next(self):
                raise StopIteration

        if self.root:
            return self.root.__iter__()
        return EmptyIter()

class Node(object):

    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

    def __iter__(self):
        if self.has_left_child():
            for child in self.left:
                yield child

        yield self.val

        if self.has_right_child():
            for child in self.right:
                yield child

运行代码的示例

bt = BinaryCont()
bt.insert(5)
bt.insert(3)
bt.insert(7)
for node in bt:
    print node

3
5
7

it = iter(bt)
type(it)
<type 'generator'>

2 个答案:

答案 0 :(得分:7)

您的__iter__方法是generator function,因为它在函数体中使用了yield。调用时,生成器函数返回生成器对象。 该对象具有__next__方法。

您的Node本身不是迭代器。它只是一个可迭代的对象;当你调用它的__iter__方法时,一个可迭代对象返回一个新的迭代器实例,这就是这里发生的事情。

答案 1 :(得分:3)

生成器非常有__next__方法。你自己不要实现它。 A&#34;功能&#34;使用yield语句不会运行您的代码。它返回一个运行代码的对象。该对象具有__next__方法。

您可能还需要注意,还有另一种使对象可迭代的机制:提供__len____getitem__方法。在这种情况下,迭代将在从零到len-1的索引上发生。