Python 为什么iterable对象不是迭代器?

Python 为什么iterable对象不是迭代器?,python,iterator,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):

这是我的密码:

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)
错误:

回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:“linehistory”对象不是迭代器

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

迭代器对象需要
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,但它们还需要实现
下一步

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

迭代器 返回迭代器对象本身

迭代器.next()
从容器中返回下一个项目

在Python 3.x中,函数名如下:

迭代器

迭代器。下一个


迭代的概念有很好的文档记录

简而言之,“iterable”是我想要迭代的对象,也称为容器。这可以是一个列表、一个字符串、一个元组或任何其他由多个项组成或可以生成多个项的内容。它具有返回迭代器的
\uuuuuuuuuuuuu iter()

“迭代器”是用于一次迭代的对象。它可以看作是一种“光标”。它有
next()
(在Python 2中)或
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。由于任何迭代器都是可迭代的(作为自己的迭代器),因此它也有返回自身的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

您可以使用
iter(obj)
获得任何iterable的迭代器

在您的示例中,
linehistory
(应该编写
linehistory
)是可移植的,因为它有一个
。用它创建的生成器对象是迭代器(与每个生成器对象一样)

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

错。见:

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

iterator.\uuu iter\uuuu()

返回迭代器对象本身。这是允许容器和迭代器与for和in语句一起使用所必需的。此方法对应于Python/CAPI中Python对象类型结构的tp_iter插槽

iterator.\uuuu next\uuuuu()

从容器中返回下一个项目。如果没有其他项,则引发StopIteration异常。此方法对应于Python/CAPI中Python对象类型结构的tp_iternext槽

但是,您可以迭代
,这是因为您的
\uuuu iter\uuu
方法是一个生成器函数,请参阅:

Python的生成器提供了一种实现迭代器协议的方便方法。如果容器对象的
\uu iter\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuo()方法作为生成器实现,它将自动返回一个迭代器对象(从技术上讲,是生成器对象),提供
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。有关生成器的更多信息,请参见屈服表达式的文档

其实


所有其他答案都是错误的(除了@glglgl,他写作风格迟钝)。您的生成器函数
\uuuu iter\uuuu()
将像这样使用
for
循环调用它一样工作

for line in lines:
    print(line)
但是因为您使用了
next(line)
,所以您必须首先使用
iter()
来获取迭代器(我假定它只是调用对象上的uu iter()


正如

一样,您还需要定义一个
next()
方法(或者对于Python 3来说是
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
方法)。
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu方法缺少:一个
方法使对象成为。使用
lines=iter(linehistory(f))
你会没事的。另请看:“glglglgl谁的写作风格迟钝”你能详细说明一下吗?@glglglglgl你说了两遍同样的话,下一次它会带来清晰的效果,也就是说,
“iterable”是我想迭代的对象
,再次是
“iterator”是用于迭代的对象
。接下来介绍
next
,并解释这是什么,然后使用生成器再次执行此操作。您基本上假设读者知道什么:迭代、next()和生成器。但主要是你没有提供例子,也没有提到引入的概念。谢谢你的评论。我增加了一些清晰度(希望如此),并提供了一个链接来帮助读者找到“原始”定义。在我的例子中(从您的第一个示例中),
line
是一个dict对象。我怎样才能从中提取出关键点(而不是遍历所有内容)?@LShaver如果你在
dict
上使用for循环,你只会得到关键点。您还可以在
dict
上使用
.keys()
,并获得一个keys iterable,其工作方式类似于上例中的
it = iter(lines)
print(next(it))