可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
- Lists can be modified in place using global list access Lists can
- List items can NOT be modified in place using the iterator object
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?
回答1:
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) {}
回答2:
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]
回答3:
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.
回答4:
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.
回答5:
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.
回答6:
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.