【问题标题】:Why does a Python iterator need a dunder iter function?为什么 Python 迭代器需要一个 dunder iter 函数?
【发布时间】:2021-01-20 02:25:56
【问题描述】:

根据documentation,需要可迭代的容器应提供__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__() 只在迭代器上调用。

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

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

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

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


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

【问题讨论】:

    标签: python-3.x iterator


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • 在重新阅读这个答案时,我实际上对所做的区别印象深刻,我最初并没有完全理解。迭代器(一次性)是您可以迭代的东西,就是这样。可迭代是可以根据需要多次提供迭代器的东西。如果可以的话,我会再次投票:-)
    猜你喜欢
    • 2014-02-16
    • 2020-05-29
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2016-08-01
    相关资源
    最近更新 更多