3

I came across a situation where I need to implement a for loop with more than one loop control variable. Basically this is what I am trying to do

Java:

for (int i=0,j=n; i<n,j>=0; i++, j--)     
    do my stuff

How do I do this in Python?

for i in range(0,n), j in range(n-1,-1,-1): 
    do my stuff

But this doesn't work. What would be the right syntax here? Also, is there a more elegant(pythonic) construct for the use-case?

4
  • What is the use case? That is, what is the loop actually going to do with those values? Commented Oct 30, 2014 at 4:45
  • does that matter? let's say something like print i*j Commented Oct 30, 2014 at 4:47
  • Yes, because often you can iterate over the actual items you're trying to use in the loop, instead of numerical indices for them. Commented Oct 30, 2014 at 4:53
  • No i and j are not being used to access arrays or anything. They are the actual numeric values that I need inside the loop. Commented Oct 30, 2014 at 4:56

3 Answers 3

7

For your specific example, it doesn't look like you really need separate variables in the loop definition itself. You can just iterate over the i values and construct the j values by doing n-i:

for i in range(0, n):
     j = n-i
     # do stuff

In general, you can't specify multiple values in the for statement if they depend on each other. Instead, use the for to iterate over some "base" value or values from which the others can be derived.

You can specify multiple values in the for loop, but they must be drawn from a single iterable:

for i, j in zip(range(0, n), range(n, 0, -1)):
    # do stuff

This takes i from the first range (0 to n-1) and j from the second (n to 1). zip creates a new iterable by componentwise pairing the elements of the iterables you give it.

The thing to remember is that Python for loops are not like loops in Java/C, which have an initialize/check end condition/update structure that repeatedly modifies some persistent loop index variable. Python for loops iterate over a "stream" of values provided by a "source" iterable, grabbing one value at a time from the source. (This is similar to foreach-type constructs in some other languages.) Whatever you want to iterate over, you need to get it into an iterable before you begin the loop. In other words, every Python for loop can be thought of as roughly analogous to something like:

 for (i=iterable.getNextValue(); iterable.isNotEmpty(); i=iterable.getNextValue())

You can't have the loop initialization be different from the loop update, and you can't have those be any operation other than "get the next value", and you can't have the end condition be anything other than "is the iterable exhausted". If you want to do anything like that, you have to either do it yourself inside the loop (e.g., by assigning a secondary "loop variable" as in my example, or by checking for a custom loop exit condition and breaking out), or build it into the "source" that you're iterating over.

Sign up to request clarification or add additional context in comments.

6 Comments

right this will work indeed. but coming from a Java background I am surprised that there is no python construct for the multi-var for-loop. i will wait a bit longer to see if there's a better answer before accepting yours
@user949110: I added a bit to my answer showing how you can specify both in the for loop, although I think that way is less readable in this case.
@BrenBarn Will enumerate also work ? If yes then could you add it to your answer too ?
@d-coder: I suppose in this case you could use enumerate(xrange(n, 0, -1)), but that is even less readable, and somewhat confusing since enumerate gives indices, which the OP says he doesn't want. (It only coincidentally gives the right values in this case.)
@BrenBarn Yes! He is using range(0,n) so it gives right values. Also I would like to mention that xrange was removed in Python 3.x and above right ?
|
1

A lot depends on iterators you want. Here's a couple of options. What they have in common is that for... in... will traverse over lists, tuples, and anything else which supports iteration. So you could loop over a list of known values or a generator which produces an arbitrary series of values. The for... in... is the same regardless.

Here's some standard python tricks:

nested loops

for i in range(10):
    for j in range (10):
        print i, j

This is simple and clear, but for complex iterations it may get very deeply nested. Here range is a generator, which means it produces an iteration over a series (in this case, 10 numbers - but it could be any arbitrary stream of values))

zip

for multiple iterators you can use zip() which creates an iterable object that produces a value from each of several of iterables at the same time. You can use multple assignment inside the for loop to grab pieces out of the zip

a = [1,2,3,4]
b = ['a','b','c','d']
for  number, letter in zip (a, b):
    print letter, ":", number
# a : 1
# b : 2
# c : 3
# d : 4

zip will stop when the first member is exhausted:

a = [1,2]
b = ['a','b','c','d']
for  number, letter in zip (a, b):
    print letter, ":", number
# a : 1
# b : 2

zip also uses generators:

test = zip (range(10), range(10,20))
for item in test: print item
#(0, 10)
#(1, 11)
#(2, 12)
#(3, 13)
#(4, 14)
#(5, 15)
#(6, 16)
#(7, 17)
#(8, 18)
#(9, 19)

itertools

For more complex iterations there's a lot of great tools in the itertools module This is particularly nice for things like getting all of the products or permutations of multiple iterators. It's worth checking out but I think it's more than you need

Comments

0

You can create a list comprehension using more than one loop control variable:

>>> n = 10
>>> stuff = [i*j for i in range(n) for j in range(n-1,-1,-1)]
>>> stuff
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, 63, 56, 49, 42, 35, 28, 21, 14, 7, 0, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0, 81, 72, 63, 54, 45, 36, 27, 18, 9, 0]

1 Comment

This is again nested loops, which isn't what he wants.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.