I would expect that in the following code the second loop overwrites the variable i of the first loop, so the inner loop will iterate i to have values 0, 1, 2 and then the outer loop, seeing that i=2 will end without doing the second iteration.
However the code seems to correctly do 6 iterations (depth 2)
I included printing i at each depth, to see in detail what is happening and it looks like the inner i is the one that can be accessed by name, while the object used by the outer loop seems to have lost a variable that references it, but still is usable by the loop.
for i in range(2):
for i in range(3):
print(f"i at depth 2: {i}")
print(f"i at depth 1: {i}")
print(f"i at depth 0: {i}")
i at depth 2: 0
i at depth 2: 1
i at depth 2: 2
i at depth 1: 2
i at depth 2: 0
i at depth 2: 1
i at depth 2: 2
i at depth 1: 2
i at depth 0: 2
I’d be interested in knowing a bit better what is happening under the hood, it seems that loops don’t really use variable names, but are directly tied to memory locations or something, so even if the outer loop object is no longer referenced by i it’s still usable.
Is there any documentation on such behaviour that I can read to understand in detail what is happening?
>Solution :
The line:
for i in range(2):
.. means "loop over the elements of range(2) (i.e., 0 and then 1) and assign the value to i during each iteration".
Similarly, the line:
for i in range(3):
.. means "loop over the elements of range(3) (i.e, 0, 1, then 2) and assign the value to i during each iteration".
So, that’s what happens:
- 0 is assigned to
i- 0 is assigned to
i- 0 is printed
- 1 is assigned to
i- 1 is printed
- 2 is assigned to
i- 2 is printed
- 2 is printed
- 0 is assigned to
- 1 is assigned to
i- 0 is assigned to
i- 0 is printed
- 1 is assigned to
i- 1 is printed
- 2 is assigned to
i- 2 is printed
- 2 is printed
- 0 is assigned to
- 2 is printed
The fact that the value assigned to i in the outer loop is never used doesn’t matter. Consider that this code would give the exact same result:
for _ in range(2):
for i in range(3):
print(f"i at depth 2: {i}")
print(f"i at depth 1: {i}")
print(f"i at depth 0: {i}")
So, nothing complicated is happening – the loops are straightforward and the assignments happen in the order specified. It’s not "i looping", it’s just "the loop assigning to i as it progresses", and the name of the first loop variable is immaterial since it is never referenced before being overwritten.