Status of PEP's?

James_Althoff at i2.com James_Althoff at i2.com
Fri Mar 1 16:47:00 EST 2002


[Jim]
> For example, one problem I had when playing with an experimental
> implementation of the "middle argument" variant mentioned above is that
the
> specific relational operators are tied to the values of the bounds.  If
you
> want to iterate from the smaller value (up) to the larger value you
write:
>
> for 1 <= var < 5:
>
> whereas if you want to iterate from the larger value (down) to the
smaller
> value you have to turn things around and write:
>
> for 5 > var >= 1:
>
> which all looks very nice when you are dealing with literal constants.
But
> suppose you have variables for the bounds, "start" and "end"?  Let's say
I
> have a function
>
> def doSomethingFromTo(start,end):
>
> The function has to test to see which of "start" and "end" is the smaller
> value in order to know whether to execute a for-loop with "<" or a
for-loop
> with ">" (and the code specified in each separate for-loop has to be
> written redundantly).  I found this to be awkward.

[Greg Ewing]
> But if you really want, you can
> always sort out the argument order before entering
> the loop, e.g.
>
>    if start > end:
>       start, end = end, start
>    for start <= i < end:
>       ...
>
> No redundant for-loop code required.

But I don't get the specified behavior, either.


[David Eppstein]
> What's wrong with
>     for min(start,end) < var < max(start,end)
> ?

It gives different results than specified.


Let's take an example.

Suppose start == 10 and end == 5

This means I want to iterate on 10,9,8,7,6,5 (ignore open vs closed -- not
relevant here) in *that* order.

In Greg's case we swap start and end and do
    for 5 <= i <= 10
and iterate 5,6,7,8,9,10 -- the right numbers but the wrong order.

In David's case we pick 5 as the min and 10 as the max do
    for 5 <= var <= 10
and iterate 5,6,7,8,9,10 -- same deal.

In other words, if I want to iterate up (smaller up to larger) I need to
write the for-loop as
    for smaller <= i <= larger:  # can *only* iterate up
but if I want to iterate down (larger down to smaller) I need to write the
for-loop with the reverse relational operators
    for larger >= i >= smaller:  # can *only* iterate down

So if you want/need "from/to" functionality for an "interval" using the
suggested for+relational idiom, you need to have two for-loops at hand,
test the bounds, *and* pick the corresponding, correct for-loop (whose
relational operators are in the correct direction).

Note that the existing range and xrange functions (when used in a
for-loop), although requiring a test on the bounds in order to determine
the correct order of the args, do *not* require the use of two for-loops in
this context.
    for i in range(n,m,step):  # can iterate up or down depending on
n,m,step

I would like to be able to create a "directional, interval-like" object
that iterates 10,9,8,7,6,5 (for example) as well as one that iterates
5,6,7,8,9,10 -- and do that with *one* construct, not two (in a for-loops,
list-comp.s, or anywhere else).  Using the much beloved (by few beside me
<wink>) "overload the divide operators" approach (just to illustrate the
point, no need to flame the syntax again <wink>), you can do this by saying
    interval_5to10 = 5 // span // 10
    interval_10to5 = 10 // span // 5
so that one for-loop does the trick
    for i in start // span // end: # can iterate up *or* down, just like
range can

The fact that the suggested for+relational idiom *does* require two loops
seems like a step backwards (again, in *this* context) to me.  Or a
limitation, at least.

Just to clarify.

Jim





More information about the Python-list mailing list