__iter__
is what gets called when you try to iterate over a class instance:
>>> class Foo(object):
... def __iter__(self):
... return (x for x in range(4))
...
>>> list(Foo())
[0, 1, 2, 3]
__next__
is what gets called on the object which is returned from __iter__
(on python2.x, it's next
, not __next__
-- I generally alias them both so that the code will work with either...):
class Bar(object):
def __init__(self):
self.idx = 0
self.data = range(4)
def __iter__(self):
return self
def __next__(self):
self.idx += 1
try:
return self.data[self.idx-1]
except IndexError:
self.idx = 0
raise StopIteration # Done iterating.
next = __next__ # python2.x compatibility.
In the comments, it was asked how you would construct and object that could be iterated multiple times. In this case, I'd recommend taking the same approach that Python takes and split the iterator from the data container:
class BarIterator(object):
def __init__(self, data_sequence):
self.idx = 0
self.data = data_sequence
def __iter__(self):
return self
def __next__(self):
self.idx += 1
try:
return self.data[self.idx-1]
except IndexError:
self.idx = 0
raise StopIteration # Done iterating.
class Bar(object):
def __init__(self, data_sequence):
self.data_sequence = data_sequence
def __iter__(self):
return BarIterator(self.data_sequence)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…