[Python-3000] Builtin iterator type

George Sakkis george.sakkis at gmail.com
Tue Nov 14 00:49:49 CET 2006


On 11/13/06, Guido van Rossum <guido at python.org> wrote:

> [Adding back python-3000 -- I'm not going to have private conversations]

Sorry, I accidentally hit reply instead of reply-all; I realized it a
minute later and I sent a cc to the list but it hasn't appeared yet..
strange.

> On 11/13/06, George Sakkis <gsakkis at rutgers.edu> wrote:
> > On 11/13/06, Guido van Rossum <guido at python.org> wrote:
> >
> > > Hm. Without knowing much of the background, this appears to be a
> > > worrysome trend away from duck typing. Why would I have to inherit
> > > from a standard class just so that I can implement next()? What's the
> > > advantage of the proposed change?
> >
> > Duck typing will still apply of course; an object that just implements
> > next() without inheriting from iter will continue to be iterable. The
> > advantage is the iterator methods and syntax sugar you get for free,
> > instead of importing them explicitly from itertools (I've noticed that
> > most of my modules lately start with a variation of "import sys,
> > itertools as it").
>
> Well, if you move the itertools functions to the base class, without
> inheriting from that base class you'd lose the itertools
> functionality. (Although many itertools functions take multiple
> generator arguments so I'm not sure how e.g. imap or izip can become
> methods without losing functionality.)

It's actually straightforward; see below.

> > 2. Augment this type with operators to implement operations currently
> > done explicitly by itertools.*.
>
> Please go over all of the itertools functions and show how they can be
> reimplemented as methods. I think you'll find most of them don't work
> this way.

There are currently 14 itertools functions; from those, only 2 don't
take an iterable argument, count() and repeat(). The rest can be
trivially rephrased as methods. Below is the updated iter class
(renamed to Iter for backwards compatibility). I didn't add imap,
ifilter, ifilterfalse and starmap as I think these should be
deprecated in favor of gencomps. Instead I added enumerate and
reversed, as I don't see why these are builtins and not itertools in
the first place.


from itertools import *

class Iter(object):

    def __init__(self, iterable): self._it = iter(iterable)
    def next(self): return self._it.next()
    def __iter__(self): return self
    def __add__(self, other): return Iter(chain(self._it, other))
    def __radd__(self,other): return Iter(chain(other, self._it))
    def __mul__(self, num): return Iter(chain(*tee(self._it,num)))
    __rmul__ = __mul__

    def __getitem__(self, index):
        if isinstance(index, int):
            try: return islice(self._it, index, index+1).next()
            except StopIteration:
                raise IndexError('Index %d out of range' % index)
        else:
            start,stop,step = index.start, index.stop, index.step
            if start is None: start = 0
            if step is None: step = 1
            return Iter(islice(self._it, start, stop, step))

    def cycle(self): return Iter(cycle(self._it))
    def takewhile(self, predicate): return Iter(takewhile(predicate, self._it))
    def dropwhile(self, predicate): return Iter(dropwhile(predicate, self._it))
    def groupby(self, keyfunc=None): return Iter(groupby(self._it, keyfunc))
    def zip(self, *others): return Iter(izip(self._it, *others))
    def enumerate(self): return Iter(enumerate(self._it))
    def reversed(self): return Iter(reversed(self._it))
    def copy(self):
        self._it, new = tee(self._it)
        return Iter(new)


Unit tests omitted for brevity.

George


More information about the Python-3000 mailing list