您所说的实际上并不取决于next
函数,而是取决于每个迭代器如何实现其next
方法。而且,虽然许多迭代器在您调用时会“提前” next
,但他们不必这样做。
原型迭代器是指向某个可迭代对象中某个位置的虚拟“指针”,它们的next
方法返回迭代器当前指向的值,并将其前进以指向可迭代对象中的下一个值。
例如,考虑通过调用iter
列表返回的迭代器。第一次调用next(i)
返回元素 0,然后下一次调用返回元素 1,依此类推。你可以像这样模拟它的行为:
class ListIterator(object):
def __init__(self, lst):
self.lst = lst
self.idx = 0
def next(self):
try:
value = self.lst[self.idx]
except IndexError:
raise StopIteration
self.idx += 1
return value
显然,这是通常的情况,因此得名next
.
但是你可以很容易地创建一个不能以这种方式工作的迭代器——不仅仅是作为某种病态类型来证明一个观点,而是实际有用的迭代器。
例如,查看itertools.repeat
. 每次调用它时,返回的迭代器itertools.repeat(10)
都会给你。你可以把它想象成一个无限长列表的迭代器,它的元素都是 all ,但这显然不是它真正的工作方式。它实际上是这样工作的:10
next
10
class RepeatIterator(object):
def __init__(self, value):
self.value = value
def next(self):
return self.value
其他迭代器通过动态计算值、从套接字中拉出缓冲区等来工作。您总是可以找到一种方法将任何迭代器视为指向某种虚拟序列中某个位置的指针,就像10
s 的虚拟无限列表,但这通常是一个延伸,在这些情况下,考虑真正发生的事情会更有帮助——调用next
方法。
顺便说一句,这在 Python 3 中更容易讨论,在那里你有一个next
调用__next__
方法的函数,而不是一个next
方法。当然,Python 3 的方式与其他特殊方法遵循相同的模式——<code>iter(i) 调用i.__iter__()
、getattr(obj, attr)
调用obj.__getattr__(attr)
和next(i)
调用i.__next__()
。