为什么可迭代对象不是迭代器?

pip*_*ipi 17 python iterator

这是我的代码:

from collections import deque

class linehistory:
    def __init__(self, lines, histlen=3):
        self.lines = lines
        self.history = deque(maxlen=histlen)

    def __iter__(self):
        for lineno, line in enumerate(self.lines,1):
            self.history.append((lineno, line))
            yield line

    def clear(self):
        self.history.clear()


f = open('somefile.txt')
lines = linehistory(f)
next(lines)
Run Code Online (Sandbox Code Playgroud)

错误:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
    TypeError: 'linehistory' object is not an iterator
Run Code Online (Sandbox Code Playgroud)

我不知道为什么linehistory对象不是迭代器,因为它已经__iter__the类中包含了方法.

CpI*_*ILL 18

实际上,

所有这些其他答案都是错误的(@glglgl 除外,他的写作风格很迟钝)。__iter__()如果您使用这样的for循环调用它,您的生成器函数将按原样工作

for line in lines:
    print(line)
Run Code Online (Sandbox Code Playgroud)

但是因为你使用过next(lines)你必须首先使用iter()来获取迭代器(我认为它只是在对象上调用 __iter__() )像这样

it = iter(lines)
print(next(it))
Run Code Online (Sandbox Code Playgroud)

正如比兹利先生指出的那样

  • “glglgl,文笔迟钝”,您能详细说明一下吗? (2认同)

glg*_*lgl 17

简而言之,"iterable"是我想要迭代的对象.它有__iter__().

但是,"迭代器"是用于迭代的对象.它有next()__next__().因为任何迭代器也是可迭代的(作为它自己的迭代器),它也有__iter__().

你可以得到任何迭代的迭代器iter(obj).

在您的示例中,linehistory(应该编写LineHistory)是可迭代的,因为它具有.__iter__().用它创建的生成器对象是一个迭代器(作为每个生成器对象).


Sup*_*Man 1

迭代器对象需要一个__iter__方法,但它们也需要实现next

迭代器对象本身需要支持以下两种方法,它们共同构成了迭代器协议:

iterator.__iter__()
返回迭代器对象本身。

iterator.next()
返回容器中的下一个项目。

Python 2.7 源代码

在 Python 3.x 中,这些是函数名称:

迭代器.__iter__()

迭代器.__next__()

Python 3.x 源代码