Iterators
In typical design pattern parlance, an iterator is an object with a next()
 method and a done()
 method; the latter returns True
 if there are no items left in the sequence. In a programming language without built-in support for iterators, the iterator would be used like this:
while not iterator.done():
item = iterator.next()
# do something with the item
In Python, iteration is available across many language features, so the method gets a special name, __next__
. This method can be accessed using the next(iterator)
 built-in. Rather than a done()
 method, Python's iterator protocol raises the StopIteration
exception to notify the client that the iterator has completed. Finally, we have the much more readable for item in iterator:
 syntax to actually access items in an iterator instead of messing around with a while
 statement. Let's look at each these in more detail.