a =[1,2]
for entry in a:
entry = entry + 1
print a
Shouldn\'t the list be mutated to[2,3]
? The result came out as [1,2]
All variables in Python contain references (i.e., pointers) to some object stored somewhere. Even integers are objects. Assignment changes the pointer to point to another object, it does not modify the item that is being pointed to.
When you do:
a = [1, 2]
for entry in a:
entry = entry + 1
The first time through the loop, entry
is made to point to the integer 1
, because that's what the first element of a
(known as a[0]
) points to.
Now, the integer 1
is not stored in the list itself, and entry
is not a pointer to a slot in the list. Rather, entry
and a[0]
point to the same object, the integer 1
.
When you do entry = entry + 1
(or just entry += 1
), entry
is changed to point to the integer 2
. However, a[0]
does not change, because you didn't change it. It still points to the integer 1
.
The Pythonic way to modify a list while iterating over it is to use enumerate()
. This gives you both the index (which you need to modify a list item) and the value from the list.
for index, entry in enumerate(a):
a[index] += 1
Here you are not actually using the existing element value, so you could also use range
:
for index in range(len(a)):
a[index] += 1
Another way to do this is with a slice assignment coupled with a generator expression. This replaces the entire contents of the list:
a[:] = (entry + 1 for entry in a)
Doing it this way has the advantage that, if the list a
also has other names, the changed list is visible through those other names. If this isn't what you want, you can also do:
a = [entry + 1 for entry in a]
This creates a new list with the updated values and makes a
point to it.