一、
As simply as I can put it:
__iter__
defines a method on a class which will return an iterator (an object that successively yields the next item contained by your object).
The iterator object that __iter__()
returns can be pretty much any object, as long as it defines anext()
method.
The next
method will be called by statements like for ... in ...
to yield the next item, andnext()
should raise the StopIteration
exception when there are no more items.
What's great about this is it lets you define how your object is iterated, and __iter__
provides a common interface that every other python function knows how to work with.
二、
Technically, iteration contexts work by calling the iter
built-in function to try to find an __iter__
method, which is expected to return an iterator object. If it’s provided, Python then repeatedly calls this iterator object’s __next__
method to produce items until a StopIteration
exception is raised. If no such __iter__
method is found, Python falls back on the __getitem__
scheme and repeatedly indexes by offsets as before, until an IndexError
exception is raised. A next
built-in function is also available as a convenience for manual iterations: next(I)
is the same asI.__next__()
.
三、exapmle
class Squares: def __init__(self, start, stop): # Save state when created self.value = start - 1 self.stop = stop def __iter__(self): # Get iterator object on iter return self def __next__(self): # Return a square on each iteration if self.value == self.stop: # Also called by next built-in raise StopIteration self.value += 1 return self.value ** 2 %python
>>>from iters import Squares
>>>for i in Squares(1, 5):
# for calls iter, which calls __iter__ ...print(i, end=' ')
# Each iteration calls __next__ ... 1 4 9 16 25
Here, the iterator object is simply the instance self
, because the __next__
method is part of this class. In more complex scenarios, the iterator object may be defined as a separate class and object with its own state information to support multiple active iterations over the same data (we’ll see an example of this in a moment). The end of the iteration is signaled with a Python raise
statement (more on raising exceptions in the next part of this book). Manual iterations work as for built-in types as well:
>>>X = Squares(1, 5)
# Iterate manually: what loops do >>>I = iter(X)
# iter calls __iter__ >>>next(I)
# next calls __next__ 1 >>>next(I)
4...more omitted...
>>>next(I)
25 >>>next(I)
# Can catch this in try statement StopIteration