Python: List Is Not Mutated After For Loop
Solution 1:
To modify the original list you could do this:
a =[1,2]
for x in range(len(a)):
a[x] = a[x] + 1print a
Or you could change your for loop to a "oneliner" like this:
a =[1,2]
a = [x + 1 for x in a]
print a
Output of either method:
[2, 3]
The difference between the methods is the first modifies the list, while the second creates a new list.
Solution 2:
No, because when you do entry = entry + 1
you create a new integer object and bind that to the name entry
, the original object bound to that name is unaffected.
Remember that in Python integer objects are immutable. However, if a
contains mutable objects, like lists, you can do this:
a = [[1], [2]]for entry in a:
entry += [1]
print a
And then the items in a
will be mutated:
output
[[1, 1], [2, 1]]
Note that if you just did entry = entry + [1]
then a
would be unchanged, due to the way simple assignment binds the new object to the name.
You may find this article helpful: Facts and myths about Python names and values, which was written by SO veteran Ned Batchelder.
Solution 3:
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 + 1forentryin 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.
Solution 4:
No, why should it?
entry
is just a name, which the for loop assigns to each integer in the list. If you subsequently reassign that name to point to a different integer, the list doesn't care.
Post a Comment for "Python: List Is Not Mutated After For Loop"