Reputation: 196
Sorry for the noob question, but someone pls explain me the inner workings of this nested for loop.
v,w = 2,4
for v in range(v):
for w in range(w):
print('v=',v,'w=',w)
If I run it like this, the output will be as follows:
v= 0 w= 0
v= 0 w= 1
v= 0 w= 2
v= 0 w= 3
v= 1 w= 0
v= 1 w= 1
v= 1 w= 2
I figured it stops 'prematurely' (the last output v= 1 w= 3 is missing) cause the last value assigned to the 'w' variable was 3 before the last loop ran.
If I run it like this, it works, but doesn't look Pythonic to say the least.
v,w = 2,4
for v in range(v):
for w in range(w):
print('v=',v,'w=',w)
w = 4
Could some please explain how this problem is best addressed?
Upvotes: 2
Views: 4155
Reputation: 15204
The most interesting thing to notice here in my opinion is that range(w)
is not updated as long as you stay in the same for v in range(v)
iteration. And that is why you get:
v = 0, w = 0
v = 0, w = 1
v = 0, w = 2
v = 0, w = 3
But, on the second iteration, when your v
becomes 1
, range(w)
gets redefined using the new w
value which is now 3
. And that is why you then get:
v = 1, w = 0
v = 1, w = 1
v = 1, w = 2
Addressing the problem as for example @wim says is simple; you just have to use different variables:
for i in range(v):
for j in range(w):
# do your thing
A side-effect of the above is that the following does execute 5 times even though it is a horrible thing to write:
v = 5
for v in range(v):
# do your thing
Upvotes: 1
Reputation: 29307
This behavior is known as variable leaking in for loops and is due to the fact that Python does not create a new variable in for loops.
At the end of for w in range(w):
, w
has value 3 so when you run the loop again it will run for range(3) and for range(4) with the original value of w
as you might have expected.
To avoid this, use a different variable for in the for
loop, as suggested in the other answers.
The only case when the for loop variable is not exposed to the surrounding function is in list comprehensions (and only in Python 3, see PEP- Generator Expressions), so for instance
>>> for v in range(v):
... print([('v=',v,'w=',w) for w in range(w)])
... print(w)
...
[('v=', 0, 'w=', 0), ('v=', 0, 'w=', 1), ('v=', 0, 'w=', 2), ('v=', 0, 'w=', 3)]
4
[('v=', 1, 'w=', 0), ('v=', 1, 'w=', 1), ('v=', 1, 'w=', 2), ('v=', 1, 'w=', 3)]
4
Upvotes: 1
Reputation: 362507
I figured it stops 'prematurely' (the last output v= 1 w= 3 is missing) cause the last value assigned to the 'w' variable was 3 before the last loop ran
Correct.
Could some please explain how this problem is best addressed?
Don't re-use the same local variable name for two different meanings:
n_v, n_w = 2, 4
for v in range(n_v):
for w in range(n_w):
print('v=', v, 'w=', w)
Upvotes: 6
Reputation: 5591
Hi Peter see the answer from wim he is correct.
Rewrite the code like below:-
v,w = 2,4
for v1 in range(v):
for w1 in range(w):
print('v=',v1,'w=',w1)
Upvotes: 0