The concept that matters here is the idea of reference . In Python, variables are references to objects that are located somewhere in memory. Let use the β arrow to indicate a link. Variable β Object. The variable on the left, the object on the right.
An array can be visualized as three variables that reference three integer objects.
a[0] β int(1) a[1] β int(2) a[2] β int(3)
Now whole objects are immutable. They cannot be changed. When you change an integer variable, you do not change the object to which the variable belongs. You cannot, because int immutable. You can make a reference to a variable another object.
Direct update
First, consider the second cycle, since it is simpler. What happens if you update the array immediately?
for i in range(0, len(a)): a[i] += 1
First let me expand the loop:
a[0] += 1 a[1] += 1 a[2] += 1
For integers a[0] += 1 equivalent to a[0] = a[0] + 1 . First, Python evaluates a[0] + 1 and gets the result int(2) . Then it changes a[0] to the int(2) link. The second and third operators are evaluated in the same way.
a = [1, 2, 3]
Indirect update
What about what I will call an βindirectβ update?
for x in a: x += 1
Deploying a loop gives this equivalent sequence of statements:
x = a[0] x += 1 x = a[1] x += 1 x = a[2] x += 1
What happens at each step, and why does the array not change?
x = a[0]
This makes the link x reference to any object a[0] . Both a[0] and x refer to the same int(1) object, but x is not directly related to a[0] . This refers to what relates to a[0] , and not to a[0] .
x += 1
This is the change referenced by x . This does not affect a[0] .
The same thing happens for the second and third appointments. As a result, x constantly changing, and the elements of a simply read, but not changed. And therefore, when the cycle ends with a , it does not change.
a = [1, 2, 3] # a[0] β int(1) # a[1] β int(2) # a[2] β int(3) x = a[0] # x β int(1) x += 1 # x β int(2) x = a[1] # x β int(2) x += 1 # x β int(3) x = a[2] # x β int(3) x += 1 # x β int(4)