这是我的代码:
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
方法。
答案 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 3.x中,这些是函数名称:
iterator .__ iter __()
迭代.__下__()
答案 3 :(得分:1)
实际上,
所有这些其他答案都是错误的(除了具有钝写作风格的@glglgl)。如果您使用__iter__()
循环调用它,那么您的生成器函数for
将按原样运行
for line in lines:
print(line)
但是因为你使用next(lines)
,你必须首先使用iter()
来获取迭代器(我假设它只是在对象上调用 iter ()),就像这样
it = iter(lines)
print(next(it))