首页 > 解决方案 > 为什么 Python 迭代器需要一个 dunder iter 函数?

问题描述

根据文档,需要可迭代的容器应该提供一个__iter__()函数来返回一个迭代器。迭代器本身需要遵循迭代器协议,这意味着它必须提供__iter__()返回自身、__next__()提供下一项或引发StopIterator异常的内容。

现在我明白了为什么在进行自己的迭代的容器中需要这两者,因为您必须同时提供迭代器和下一个项目:

class ObjAndIter:
    def __init__(self):
        pass
    def __iter__(self):
        return self
    def __next__(self):
        # return something intelligent or raise StopIterator

for i in ObjAndIter():
    pass

但是,在迭代器是不同类型的情况下,我看不到迭代迭代器本身的用例。考虑一个(人为的)类,它只提供一个迭代器以从给定数字向上计数到某个限制:

class MyObj:
    class MyIter:
        def __init__(self, start, end):
            self._num = start - 1
            self._end = end

        def __next__(self):
            self._num += 1
            if self._num > self._end:
                raise StopIteration
            return self._num

        #def __iter__(self): # This is apparently required but
        #    return self     #   it runs fine without it.

    def __init__(self, start, end):
        self._start = start
        self._end = end

    def __iter__(self):
        return self.MyIter(self._start, self._end)

x = MyObj(5, 10)
for i in x:
    print(i)

现在这似乎适用于以下情况:

x = MyObj(5, 10)
for i in x:
    print(i)

尽管迭代器不遵循迭代器协议 - 它提供__next__()但不提供__iter__(). 该__iter__()函数仅在容器上调用,并且__next__()仅在迭代器上调用。

现在如果没有迭代器 __iter__()函数,我发现您将无法执行以下操作:

x = MyObj(5, 10)
xiter = x.__iter__()
for i in xiter:
    print(i)

但是我很难想象何时需要在迭代器(而不是容器)上创建迭代器。

所以我的问题是这个。在什么情况下我需要这样做?没有它,迭代器协议似乎毫无意义,除非容器必须提供__iter__()并且迭代器必须提供__next__()


顺便说一句,我已经看到了这个问题及其答案,但它们似乎没有涵盖为什么迭代器需要是可迭代的。我可以很好地看到它使代码更容易迭代容器迭代器,但这个问题是关于为什么后者甚至是必要的。

标签: python-3.xiterator

解决方案


迭代器需要可迭代以支持 for 循环和 iter()。

这导致:为什么要迭代迭代器?

因为有时您会直接获得迭代器,例如打开的文件或生成器函数:

>>> def gen():
...     yield 1
...     yield 2
...
>>> it = gen()
>>> hasattr(it, '__next__')
True

这导致:为什么 Python 的某些部分返回一个 interator 而不是 iterable?

这是一种判断事物“不可倒带”/“一次性迭代”的方式。因为返回一个可迭代对象会说“您可以在其上调用 iter() 两次以对其进行两次迭代”,这是错误的。


推荐阅读