PEP 284, Integer for-loops

David Eppstein eppstein at ics.uci.edu
Wed Mar 6 20:57:57 EST 2002


In article <slrna8df64.utc.grey at teleute.dmiyu.org>,
 Steve Lamb <grey at despair.dmiyu.org> wrote:

> On Wed, 06 Mar 2002 16:57:03 -0800, David Eppstein <eppstein at ics.uci.edu>
> wrote:
> > I think you have made my point for me, that range is hard to use 
> > correctly.  Did you try running range(n-1,0)?  What list did it give you?
> 
> >>> range(-10,0)
> >>> [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]

I started with a positive number n, and claimed that it was hard to 
create and understand expressions such as range(n-1,-1,-1).
You said that if that was so hard, I should instead simply create 
range(n-1,0) and reverse it.

range(n-1,0) is empty when n is positive.  You should have told me to 
reverse range(n).  So, clearly, you did not understand the expression 
range(n-1,-1,-1), contradicting your claim that range is easy to 
understand.

And of course, this only helps when you want the reversal of a half-open 
interval, it still does nothing about the understandability of closed or 
open intervals.

> And?  How does this prove your point other than some minor nit I'm sure
> you're going to pick?  Point stands, there are other ways of doing it.

I agree, there are already ways to do it. There are already ways to do 
everything you might ever want to do in Python, because like most 
sensible languages it's Turing-complete.  So should we stop trying to 
improve the language?

My point is that the ways that exist now are either cumbersome (create 
a range then reverse it then loop over the reversed range, use a while 
loop instead of a for loop) or difficult to program correctly and 
difficult to understand once programmed (multi-parameter range), and 
that the proposed syntax gives a simple easy-to-understand alternative.

Anyway, according to
<http://groups.google.com/groups?selm=001101beae49$39af7bc0$949e2299@tim>
it's not a problem if there's more than one way of doing things, but 
there should preferably one obvious way.  This proposal would give one 
obvious way of doing most integer loops.

> While I've got your attention, let me ask you this.  In your notation how
> would you do the following?
> 
> for x in range(n-1,-1,-2):
> 
>     That, unlike the allusion you made above, is not a nit. 

Stops to think... range starts with n-1 ... can't understand the second 
argument before I see the third ... steps downward so starting with n-1 
should be interpreted as all numbers less than n rather than all numbers 
greater than n-2 ... step size is 2 ... now we can go back to the second 
argument, we stop before we get to -1, which with a step size of 2 means 
we stop either at 0 or 1.  Ok, what you want is almost like
    for n > x >= 0
but you want to skip every second value.

That's not covered by the current proposal.  It's supposed to be an 
improvement, not a panacea -- now is a good time for another Tim-quote 
"now is better than never", which is what we'll get if we wait for a 
perfect solution to all our problems.

It's hard to tell without some context (and I'm not convinced a context 
exists in which this is the loop you want), but if I had to write this 
loop, without further information on where n came from or whether it's 
odd or even, I'd probably skip the range() and go for:

    x = n - 1
    while x >= 0:
        ...loop body...
        x -= 2

of course, that requires more care about not continuing from the middle 
of the loop, and you have to look multiple places to even figure out 
that it's a loop over a progression of integers, but even so I think 
it's preferable to range(n-1,-1,-2).

Another possibility, depending on *why* you want to skip every second 
value, is:

    for n > x >= 0:
        if x & 1 != n & 1:
            ...loop body...

which could likely be simplified if we know the parity of n in advance.



More information about the Python-list mailing list