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.