On 10/8/15, Steven D'Aprano <st...@pearwood.info> wrote:
>
> That's one solution, but it is certainly possible for the class to be
> its own iterator, in which case it needs to follow two rules:
>
> (1) self.__next__() needs to return the next value, or raise
> StopIteration;
>
> (2) self.__iter__() needs to return self;
>
> and of course like all dunder methods __next__ and __iter__ need to be
> defined on the class itself, not on the instance.

Except this is generally a bad way to iterate a reiterable. Without a
separate iterator, there's no simple way to maintain state for
concurrent iterations.

file types are an exception. A file is reiterable (i.e. by seeking
back to 0), but the OS file pointer makes a file naturally an
iterator. Thus getting concurrent iterations of a disk file requires
separate file objects that have separate OS file pointers.

FrozenDict.next is an example of what not to do:

    def next(self):
        try:
            value = self.__kwargs.items()[self.__counter][0]
        except IndexError:
            raise StopIteration
        self.__counter += 1
        return value

In Python 2 this iterates the dict's keys by creating a list of (key,
value) tuples -- every time next() is called. In Python 3, you'd have
to explicitly create the list using list(self.__kwargs.items()). The
design also lacks support for concurrent iterations, and not even
multiple iterations since __counter isn't reset in __iter__.

The simple approach is to have __iter__ return an instance of the
wrapped dict's iterator. There's no reason to reinvent the wheel. Plus
in the non-frozen case, the built-in dict iterators are smart enough
to raise an error when the dict is modified, since it's assumed that
any modification to the hash table invalidates the iteration.
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to