About iterators in python

If I have the following list:

a = [1, 2, 3] 

And I run the following code:

 for x in a: x += 1 

It does not seem to change list a .

However, if I do the following:

 for i in range(0, len(a)): a[i] += 1 

This will change the contents of "a".

So, I think x and a[i] relate to elements a differently. What exactly makes the difference? How do they relate to a elements?

+4
source share
4 answers

When you iterate over a list, each element is inferior in turn. However, there are different types of objects. mutable and unchanging. When you do something like:

 a += 1 

with an immutable object, it roughly translates:

 a = a + 1 

Now in this case, you take a link to object a , add 1 to it to create a new object . Then you name this new object a . Note that if we do this, iteration, we don’t touch the list at all. We continue to create new objects and assign them a name a .

This is a different value for the mutable object. Then a += 1 actually changes the object in place. Thus, the list will see the change, because the object that it holds has changed (mutated). (With an immutable object, the object contained in the list was not changed because it cannot be). See this question for more information.

It also makes it clearer what happens when you repeat indexes. you create a new integer and you put it on the list (forgetting everything that was in this slot before).

+5
source

When you speak,

 for x in [1,2,3]: x+=1 

You say, temporarily save x as a variable and add it to this temporary save. When you move on to the next iteration, the scavenger destroys this variable because it is temporary. x is not a place on the list. This is the value of this place in the list.

Edit: when I say that he is leaving, I was not clear with my words. It happens that every time through the loop, x is replaced with a different value, and therefore what happened before that goes away (if you have not done something else with it). However, with the operations you use, you do not change the values ​​of any elements in the list. My bad for confusion.

If you do it the other way,

 for x in range(len(lst)): lst[x] += 1 

Then you talk about the values ​​of the list. x is the index of the variable and therefore can change the value of the list value at this point.

+3
source

The concept that matters here is the idea of reference . In Python, variables are references to objects that are located somewhere in memory. Let use the β†’ arrow to indicate a link. Variable β†’ Object. The variable on the left, the object on the right.

An array can be visualized as three variables that reference three integer objects.

 a[0] β†’ int(1) a[1] β†’ int(2) a[2] β†’ int(3) 

Now whole objects are immutable. They cannot be changed. When you change an integer variable, you do not change the object to which the variable belongs. You cannot, because int immutable. You can make a reference to a variable another object.

Direct update

First, consider the second cycle, since it is simpler. What happens if you update the array immediately?

 for i in range(0, len(a)): a[i] += 1 

First let me expand the loop:

 a[0] += 1 a[1] += 1 a[2] += 1 

For integers a[0] += 1 equivalent to a[0] = a[0] + 1 . First, Python evaluates a[0] + 1 and gets the result int(2) . Then it changes a[0] to the int(2) link. The second and third operators are evaluated in the same way.

 a = [1, 2, 3] # a[0] β†’ int(1) # a[1] β†’ int(2) # a[2] β†’ int(3) a[0] += 1 # a[0] β†’ int(2) a[1] += 1 # a[1] β†’ int(3) a[2] += 1 # a[2] β†’ int(4) 

Indirect update

What about what I will call an β€œindirect” update?

 for x in a: x += 1 

Deploying a loop gives this equivalent sequence of statements:

 x = a[0] x += 1 x = a[1] x += 1 x = a[2] x += 1 

What happens at each step, and why does the array not change?

 x = a[0] 

This makes the link x reference to any object a[0] . Both a[0] and x refer to the same int(1) object, but x is not directly related to a[0] . This refers to what relates to a[0] , and not to a[0] .

 x += 1 

This is the change referenced by x . This does not affect a[0] .

The same thing happens for the second and third appointments. As a result, x constantly changing, and the elements of a simply read, but not changed. And therefore, when the cycle ends with a , it does not change.

 a = [1, 2, 3] # a[0] β†’ int(1) # a[1] β†’ int(2) # a[2] β†’ int(3) x = a[0] # x β†’ int(1) x += 1 # x β†’ int(2) x = a[1] # x β†’ int(2) x += 1 # x β†’ int(3) x = a[2] # x β†’ int(3) x += 1 # x β†’ int(4) 
+2
source

Think of it like in your first loop, x will simply replace each element in a. This is not the actual element in a (although by id() it is because they both refer to the same object). When you do x += 1 , you simply change the value of x , not the value in the list.

In your second for-loop, you are actually modifying the list by doing a[i] += 1 .

+1
source

All Articles