Reputation: 309
Simple example:
myList = [1, 2, 3, 4, 5]
for obj in myList:
obj += 1
print myList
prints
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
while:
myList = [1, 2, 3, 4, 5]
for index in range(0,len(myList)):
myList[index] += 1
print myList
prints
[1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
Conclusion:
All example code I can find uses the global list accessors to modify the list inplace. Is it so evil to modify a list iterator?
Upvotes: 8
Views: 6564
Reputation: 150977
I think you've misunderstood what an "iterator object" is. A for
loop is not an iterator object. For all intents and purposes, a for loop like this:
myList = [0, 1, 2, 3, 4]
for x in myList:
print x
does this (but more efficiently and less verbosely):
i = 0
while i < len(myList)
x = myList[i]
print x
i += 1
So you see, any changes made to x
are lost as soon as the next loop starts, because the value of x
is overwritten by the value of the next item in the list.
As others have observed, it is possible to alter the value of a list while iterating over it. (But don't change its length! That's where you get into trouble.) One elegant way to do so is as follows:
for i, x in enumerate(myList):
myList[i] = some_func(x)
Update: It's also important to understand that no copying goes on in a for loop. In the above example, i
and x
-- like all variables in Python -- are more like pointers in C/C++. As the for loop progresses, obj
points at myList[0]
, myList[1]
, etc, in turn. And like a C/C++ pointer, the properties of the object pointed to are not changed when the pointer is changed. But also like a C pointer, you can directly modify the thing pointed at, because it's not a copy. In C, this is done by dereferencing the pointer; in Python, this is done by using a mutable object. That's why NPE's answer works. If i
and x
were even shallow copies, it wouldn't be possible to do what he does.
The reason you can't directly change int
s the way you can change list
s (as in NPE's answer), is that int
s aren't mutable. Once a 5
object is created, nothing can change its value. That's why passing around a pointer to 5
is safe in Python -- no side-effects can occur, because the thing pointed to is immutable.
Upvotes: 7
Reputation: 49826
You are confused. Consider your first snippet:
myList = [1, 2, 3, 4, 5]
for obj in myList:
obj += 1
print a
obj
is not some kind of magical pointer into the list. It is a variable which holds a reference to an object which happens to also be in myList. obj += 1
has the effect of increasing the value stored in obj
. Your code then does nothing with that value.
To be clear: There are no copies in this code example. obj is a variable, which holds an object in the list. That is all.
Upvotes: 1
Reputation: 500317
The reason obj += 1
does not do what you expect is that this statement does not modify obj
in-place. Instead, it computes the new value, and rebinds the variable obj
to point to the new value. This means that the contents of the list remain unchanged.
In general it is possible to modify the list while iterating over it using for obj in myList
. For example:
myList = [[1], [2], [3], [4], [5]]
for obj in myList:
obj[0] += 1
print(myList)
This prints out:
[[2], [3], [4], [5], [6]]
The difference between this and your first example is that here, the list contains mutable objects, and the code modifies those objects in-place.
Note that one could also write the loop using a list comprehension:
myList = [val+1 for val in myList]
Upvotes: 7
Reputation: 12881
Modification in list is allowed. Your code examples arbove are pretty garbled...
myList = [1, 2, 3, 4, 5]
for index in range(0,len(myList)):
myList[index] += 1
print myList
This works.
Upvotes: 0
Reputation: 2362
in for obj in myList:
, in every iteration, obj
is a (shallow) copy of the element in myList
. So the change on the obj
does nothing to myList
's elements.
It's different with the Perl for my $obj (@myList) {}
Upvotes: 6
Reputation: 15357
In the first example the integer is copied into obj which is increased by 1. The list is not changed.
If you would use a class instance and perform operations on it, it would be changed.
Upvotes: 0