[Python-Dev] Re: PEP 322: Reverse Iteration

Alex Martelli aleaxit at yahoo.com
Tue Nov 4 16:47:45 EST 2003


On Tuesday 04 November 2003 10:00 pm, Paul Moore wrote:
   ...
> Arguing that irange() is too similar to range() and xrange() is
> closer, but I'd say that irange is the *right* way to do it. [x]range

Agreed.  The reverse= optional argument would be delightful gravy
for me, but I could do without and not suffer too badly IF reversed
was available: where I now have

     if godown:
         iseq = xrange(len(sq)-1, start-1, -1)
     else:
         iseq = xrange(start, len(sq), 1)
     for index in iseq:
         ...

and dream of compacting it all the way to:

     for index in irange(start, len(sq), reverse=godown):
         ...

I could do something like:

     iseq = irange(start, len(sq))
     if godown: iseq = reversed(iseq)
     for index in iseq:
         ...

And after all I have found only that one use case where I need to
loop either forward or backward in my Python code.  I expected more
because I remember how horribly constraining Pascal's strong separation
between iteration forwards and backwards (for i := a to b do ...  vs
for i :- b downto a do...) felt compared to being able to just code
"DO 10 I = IST, ITO, IDELTA" in Fortran -- lo that many years ago.
I guess I write different kinds of programs these days.

> should be relegated to backward-compatibility tools, much like the
> file xreadlines() method and the xreadlines module.

Seconded.

> Raymond - are you dead set against an irange() function in itertools?
> Assume for now that it's a simple version without a reverse argument.

...and that we ALSO get your cherished reversed built-in -- there is most
emphatically no mutual incompatibility between them...


> Raymond seems very protective of the concept of reversed() as a
> builtin. I'm not saying that's wrong, but I *personally* haven't seen
> enough evidence yet to be convinced either way. The i{rev}range()

I'm slowly coming to accept it -- it's sure way more appropriate as a
built-in than many that currently crowd the builtins namespace.

> issues seem to be getting caught up in this.
>
> My view:
>
> 1. I think a "plain" irange() would be useful to add into itertools.

Yes!

>    In the (very) long term, it could replace [x]range, but that's less
>    of an issue to me.

It's probably more important to me, I guess.

> 2. A way of getting a reversed {i,x}range() has some clear use cases.
>    This seems useful to add (although here, I'm going on evidence of
>    others' code - in my code I tend to loop over containers much more
>    often than over ranges of numbers).

Me too -- by now I've replaced basically all the old
    for i in xrange(len(seq)):
        value = seq[i]
        ...
into shiny new
    for i, value in enumerate(seq):
        ...

Admittedly some reverse iterations are like that -- and being able to code

    for i in revrange(len(seq)):
        value = seq[i]
        ...

while better than (eek) "for i in xrange(len(seq)-1, -1, -1)):", still is NOT
quite as smooth as

    for value in reversed(seq):
        ...

or reversed(enumerate(seq)) if the index IS needed.

BTW, I do have spots where:

    seq.reverse()

    try: 
        #...region of code where seq is used reversed...
    finally: seq.reverse()    # put it back rightside-up again

(including one where I had forgotten the try/finally -- as I found out while
looking for these cases...).  Of course this only works because seq is a
list and it might have all sort of downsides (e.g. if this was multithreaded
code, which it isn't, it might interfere with other uses of seq; if seq was a
global this function couldn't be recursive any more; ...).

All in all I think those would benefit from reversed(seq) even if it has to
be called in more spots within the "region of code".


> 3. A general reversed() function seems theoretically useful, but the
>    concrete use cases seem fairly thin on the ground. I'm broadly in
>    favour, because I (possibly like Raymond) have a bias for clean,
>    general solutions. But I can see that "practicality beats purity"
>    may hold here.

Funny, I originally felt queasy (about it being a built-in only) for "purity"
about the overcrowded builtins namespace.  I'm seeing enough use
cases (even if irange DID grow a wonderful reverse= optional arg...)
that practicality is gradually winning me over.  I.e., practicality beats
purity is what is winning me over, while to you it suggests dampening
your "broadly in favour"...  we both mention iterating over sequences
more than over indices, but to me that's a suggestion that reversed
has a place, while you don't seem to think that follows...


> My proposals:
>
> 1. Add a plain irange() to itertools.

Yes!!!

> 2. IF the general reversed() is deemed too theoretical, add EITHER a
>    reverse argument to irange, or an irevrange to itertools. Both feel
>    to me a little iffy, but that's my generality bias again.
> 3. IF the general reversed() is accepted (builtin or not) leave the
>    irange function in its simple form.

Sigh, OK, I guess.  If I had to choose, reversed + irange plain only,
or no reversed + irange w/optional argument, I guess I would grudgingly
choose the former (having shifted my opinion).  But I'd really like BOTH
reversed (lets me iterate on sequence rather than on indices, often)
AND irange with optional reversed= ... no irevrange please...


> > Sorry, I have to push back on that.  We still need to contain the
> > growth of the language, and that includes the set of builtins and (to
> > a lesser extent) the standard library.  You have to show that this is
> > truly important enough to add to the builtins.  Maybe you can propose
> > to take away an existing builtin to make room *first*.
>
> xrange (in favour of itertools.irange())? :-)

Seconded.  Neal Norwitz' "little list" has plenty more useful suggestions,
though I wouldn't accept it as entirely sound.


> [Personally, I'm still not 100% sure I see Raymond's strong reluctance
> to have reversed() in itertools, but as both are his babies, and he

Actually, I do: itertools shouldn't be limited to accepting sequences,
they should accept iterator arguments.

> clearly has a very definite vision for both, I don't feel that I want
> to argue this one with him].

You have a point -- Raymond definitely HAS an overall vision on
iterators &c and he's deserved lots of listening-to even though we
can't quite see some specific point.


Alex




More information about the Python-Dev mailing list