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

时间:2015-11-27 11:07:00

标签: 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)

错误:

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

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

4 个答案:

答案 0 :(得分:15)

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

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

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

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

答案 1 :(得分:3)

  

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

错误。见Iterator Types

  

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

     

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

     

iterator.__next__()
  从容器中返回下一个项目。如果没有其他项,请提高StopIteration异常。此方法对应于Python / C API中Python对象的类型结构的tp_iternext槽。

但是你可以迭代lines,因为你的__iter__方法是生成器函数,请参阅Generator Types

  

Python的生成器提供了一种实现迭代器协议的便捷方法。如果容器对象的__iter__()方法被实现为生成器,它将自动返回提供__iter__()__next__()方法的迭代器对象(技术上,生成器对象)。有关生成器的更多信息可以在yield表达式的文档中找到。

答案 2 :(得分:1)

Iterator对象需要__iter__方法,但他们还需要实现next

  

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

     

迭代器ITER .__ __()
  返回迭代器对象本身。

     

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

Python 2.7 Source

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

  

iterator .__ iter __()

     

迭代.__下__()

Python 3.x Source

答案 3 :(得分:1)

实际上,

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

for line in lines:
    print(line)

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

it = iter(lines)
print(next(it))

Mr.Beazley points out

相关问题