Failed to change list iterator in Python?

A 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] 

a

 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 changed in place using global list access lists.
  • List items cannot be changed in-place using an iterator object

All the code examples I can find use global access lists to modify the list in place. Is it wrong to change a list iterator?

+6
source share
6 answers

in for obj in myList: at each iteration, obj is a (shallow) copy of the element in myList . Thus, a change in obj does nothing for myList elements.

It is different with Perl for my $obj (@myList) {}

+5
source

The reason obj += 1 does not do what you expect is because this statement does not change obj in place. Instead, it computes the new value and double-checks the obj variable to indicate the new value. This means that the contents of the list remain unchanged.

In general, you can change the list by iterating over it using for obj in myList . For instance:

 myList = [[1], [2], [3], [4], [5]] for obj in myList: obj[0] += 1 print(myList) 

This produces:

 [[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 these objects in place.

Note that you can also write a loop using list comprehension:

 myList = [val+1 for val in myList] 
+6
source

I think you misunderstood what an "iterator object" is. The for loop is not an iterator object. For all goals and objectives, for the cycle as follows:

 myList = [0, 1, 2, 3, 4] for x in myList: print x 

does this (but more efficiently and less thoroughly):

 i = 0 while i < len(myList) x = myList[i] print x i += 1 

So, you see that any changes made to x are lost as soon as the next cycle starts, because the value of x overwritten by the value of the next element in the list.

As others have observed, you can change the value of a list during iteration over it. (But don't change its length! That's where you get into trouble.) One elegant way to do this is:

 for i, x in enumerate(myList): myList[i] = some_func(x) 

Update . It is also important to understand that copying is not performed in the for loop. In the above example, i and x - like all variables in Python - are more like pointers to C / C ++. As the loop progresses, the obj points to myList[0] , myList[1] , etc., in turn. And like a C / C ++ pointer, the properties of the object that it points to do not change when the pointer changes. But just like a C pointer, you can directly change by pointing to a thing, because it is not a copy. In C, this is done by dereferencing a pointer; in Python, this is done using a mutable object. This is why NPE works. If i and x were even shallow copies, it would be impossible to do what he does.

The reason you cannot directly change the int way of changing list (as in NPE's answer) is because int not changing. Once object 5 is created, nothing can change its meaning. Therefore, if passing around a pointer to 5 safe in Python - there can be no side effects, because the specified thing is immutable.

+4
source

You are confused. Consider your first snippet:

 myList = [1, 2, 3, 4, 5] for obj in myList: obj += 1 print a 

obj not some kind of magic pointer in the list. This is a variable that contains a reference to an object that also takes place in myList. obj += 1 affects the increase in the value stored in obj . Then your code does nothing with this value.

To be clear: there are no copies in this code example. obj is a variable that contains the object in the list. It's all.

+1
source

In the first example, the integer is copied to obj, which is incremented by 1. The list does not change.

If you use an instance of a class and perform operations on it, it will be changed.

0
source

Modification in the list is allowed. Your arbove code examples are pretty distorted ...

 myList = [1, 2, 3, 4, 5] for index in range(0,len(myList)): myList[index] += 1 print myList 

It works.

0
source

Source: https://habr.com/ru/post/909186/


All Articles