[Python-bugs-list] [ python-Feature Requests-736490 ] A way to iterate over several variables at once

SourceForge.net noreply@sourceforge.net
Thu, 15 May 2003 06:11:33 -0700


Feature Requests item #736490, was opened at 2003-05-12 15:14
Message generated for change (Comment added) made by alexanro
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=736490&group_id=5470

Category: Python Interpreter Core
Group: None
Status: Closed
Resolution: Rejected
Priority: 5
Submitted By: Alexander Rødseth (alexanro)
Assigned to: Skip Montanaro (montanaro)
Summary: A way to iterate over several variables at once

Initial Comment:
Okay. Here's the problem (which occurs frequently in
graphics programming):

I have, say, variables "red", "green" and "blue". Now I
want to iterate "red" from 0 to 63, "green" from 10 to
127 and "blue" from 0 to 255 - all at the same time,
and I really, really miss a nice way to do this in
Python. Here's my suggestion for how this could be
done, (in a better world):

for red, green, blue in [0..63], [10..127], [0..255]:
   print red, green, blue

(the ".." is taken from my previous suggestion, so that
[0..63]
simply means "range(0, 63 + 1)")

My idea is that the above code would be translated to
something like this (please notice the subtle elegancy
of the two lines above, compared with the ones below...):

red_list = range(0, 63 + 1)
green_list = range(10, 127 + 1)
blue_list = range(0, 255 + 1)
longest = max(len(red_list), len(green_list),
len(blue_list))
red_inc = (red_list[-1] - red_list[0]) / float(longest)
green_inc = (green_list[-1] - green_list[0]) /
float(longest)
blue_inc = (blue_list[-1] - blue_list[0]) / float(longest)
red = red_list[0]
green = green_list[0]
blue = blue_list[0]
for count in range(longest):
        print int(red), int(green), int(blue)
        red += red_inc
        green += green_inc
        blue += blue_inc

That's about it. :)

(And yes, you could possibly rewrite the "long version"
above, in an even cleaner and nicer manner, but still!)

----------------------------------------------------------------------

>Comment By: Alexander Rødseth (alexanro)
Date: 2003-05-15 13:11

Message:
Logged In: YES 
user_id=679374

After montanaro's comment, I agree that this might be too
specific to add to Python. :)

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2003-05-12 17:23

Message:
Logged In: YES 
user_id=80475

FYI, for your applications, Numeric may be very helpful.  It 
has many tools for simulateously manipulation several 
vectors of the same length

It includes functions like Matlab's linspace() and some non-
linear variants that address your use case.

With linspace() or an equivalent in hand, use zip() to loop 
over the vectors at the same time (lockstep iteration).

----------------------------------------------------------------------

Comment By: Skip Montanaro (montanaro)
Date: 2003-05-12 16:33

Message:
Logged In: YES 
user_id=44345

This is really very counterintuitive.  At one point you say that [0..63] is the
same as range(0, 63+1).  By extension, [10..127] and [0..255] should also
translate to relevant range() calls with step sizes of 1.  However, that's not
what your code does.  You compute the longest sequence and then use
that to divide the two shorter sequences into an equal number of steps.

It seems you're simply asking for a straight line ramp from (0,10,0) to
(63, 127, 255).  Image manipulation programs I've used in the past 
have offered many other ways to proceed from one point in rgb space
to another besides simple ramps, so while your desire is pretty common,
it's hardly exhausts the reasonable ways to go from point A to point B.

Why not write a generator function which takes starting and ending points
and a step size, then returns each point in the ramp in turn, something like
this only lightly tested code:

def ramp(p1, p2, nsteps):
    "return nsteps points from p1 to p2"
    stepsize = ((p2[0]-p1[0])/float(nsteps),
                (p2[1]-p1[1])/float(nsteps),
                (p2[2]-p1[2])/float(nsteps))
    for i in range(nsteps):
        yield (p1[0]+(stepsize[0]*i),
               p1[1]+(stepsize[1]*i),
               p1[2]+(stepsize[2]*i))

(Use range(nsteps+1) if you want to include the endpoint).

You would then use it like so:

for red, green, blue in ramp((0, 10, 0), (63, 127, 255), 128):
    print red, green, blue

I think this request is too specific for adding to Python.

----------------------------------------------------------------------

Comment By: Alexander Rødseth (alexanro)
Date: 2003-05-12 15:21

Message:
Logged In: YES 
user_id=679374

One should possibly also include a way to specify the number
of wanted steps.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=736490&group_id=5470