__next__ and StopIteration

Rob Gaddi rgaddi at technologyhighland.invalid
Mon Feb 9 14:27:04 EST 2015


On Mon, 09 Feb 2015 11:14:55 -0800, Charles Hixson wrote:

> I'm trying to write a correct iteration over a doubly indexed container,
> and what I've got so far is:    def __next__ (self):
>          for row    in    range(self._rows):
>              for col in range(self._cols):
>                  if self._grid[row][col]:
>                      yield    self._grid[row][col]
>                  #end    if
>              #end    for col
>          #end    for row raise    StopIteration
> 
> What bothers me is that it doesn't look like it would continue to raise
> StopIteration if it were called again, which is what
> https://docs.python.org/3/library/stdtypes.html#iterator.__next__ says
> is correct.  How should this be fixed?

You're mixing metaphors.  You don't iterate over containers, you iterate 
over iterators that are returned to you by containers.  So the container 
class itself has a __iter__ method, which returns a custom iterator 
object that has a __next__ method.  Which is a lot of work.

Or, you write your __iter__ like so:

def __iter__ (self):
    for row in range(self._rows):
        for col in range(self._cols):
            if self._grid[row][col]:
                yield self._grid[row][col]

In which case, Python's magic handling of yield handles the creation of 
the iterator object and the raising of StopIteration at the end of the 
__iter__ function all by itself.

Or you write your __iter__ like so:

def __iter__(self):
    return (self._grid[row][col]
        for col in range(self._cols)
        for row in range(self._rows)
        if self._grid[row][col]
    )

In which case you've returned a generator expression, which is a 
shorthand way of making an iterator.  All extremely equivalent and a 
matter of personal taste (I'd probably opt for the yield one myself).

-- 
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order.  See above to fix.



More information about the Python-list mailing list