On 10/8/15, Steven D'Aprano <[email protected]> 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 - [email protected]
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor