2

I am coming to ask you another basic question again. :) I want to change a list via for-loop.(sorry to bother, but i am new....)

Here is the first script:

L=[1,2,3]
i=0
for a in L:
    L[i]+=1
    i+=1
print(L)
print(a)

I got:

L:[2,3,4]
a: 3

This is exactly what i want. But i notice that if i change the script to this:

L=[1,2,3]
for i in L:
    i+=1
print(L)
print(i)

And i got:

L:[1,2,3]
i:4

I can understand that i must be 4. But the question is why the list L doesn't change. In my opinion, the objects in the list are given to the variable i. So variable i is the one who can edit the object. So basically, the list should change. Actually, however, it stays the same.

Can someone explain this?

Thank you!

5
  • 1
    i is just a looping variable. Why do you think changing i should change value in list? Commented Jun 22, 2018 at 11:04
  • According to your code snippet, the list "L" is not suppose to change as "i" is just a counter veriable and holds single element from "L" every time it iterate. Commented Jun 22, 2018 at 11:07
  • @Austin,@Sonam Mohite, because i think the element in the list (the objects) was given to the variable i. This is the same as i = L[0], i =2. Then L[0]=2 Commented Jun 22, 2018 at 11:10
  • @Harry You can find why value is not changed in the above link. Commented Jun 22, 2018 at 11:13
  • ok! Thank you! I will have a look Commented Jun 22, 2018 at 11:16

5 Answers 5

5

This has to do with what Python "variables" really are: name pointings to objects. Think of it as a dictionary with names as keys and objects as values.

In your for loop, i initially points to the current iteration item in the list, ie i points to L[0], then to L[1] etc. But when you do i += 1 - which actually translates to i = i+1 - you rebind i so that it points to another object. This only affects the name i (what value the key holds), not the object it was pointing to before, so your list is indeed not changed.

For a more in-depth explanation, you want to read Ned Batchelder's excellent article. This will save you a lot of time and frustrations ;)

NB : for your example snippet, the proper way to update your list in place is to use enumerate:

for index, value in enumerate(L):
    L[index] = value + 1

or to update the whole list inplace with a list comprehension:

L[:] = [value+1 for value in L]
Sign up to request clarification or add additional context in comments.

3 Comments

yes! What a perfect explanation! Thank you!
@Harry I second Bruno's recommendation to read Ned's article. In fact, when I read your question I almost posted a link to that article in a comment, until I saw that it was already linked in this answer. There's a shorter article with nice diagrams on this important topic at Other languages have "variables", Python has "names".
@PM2Ring, thank you! i will have a look! thank you!
1

But the question is why the list L doesn't change

Because if you assign anything to i, it won't affect L[i].

The solution is either what you have proposed, or looping through the indices:

for index, item in enumerate(L):

Another approach is to use a list comprehension

L[:] = [i + 1 for i in L]

2 Comments

I see, but i think the list are mutable. I can change the value of the original list instead of make some change and copying it to a new one?
L = [i + 1 for i in L] will NOT change the list in place, so it doesn't do what the OP asks for. It has to be L[:] = [i + 1 for i in L] instead.
1

Thanks for all your answers! But this link is really comprehensive. https://nedbatchelder.com/text/names.html This is the same as:

m=[1,2,3]
i=m[0]  #here i refers to m[0], namely 1
i=4     #here i refers to a new value

The result is obviously:

m=[1,2,3]
i=4

For the reason that the int-name can't be changed originally. Once the value of i changed, it refers to another value (object). So the List won't change.

Thank you all the same.

2 Comments

If you understand Ned's article you'll understand why this 3 line program does what it does: lst = [[1],[2],[3]] for a in lst: a *= 2 print(lst)
@PM2Ring! it duplicated. thanks!
-1

When you do your loop

for i in L :
    i+=1

You never ask Python to change your list L. In fact, you just update i. At first, i = L[0] = 1, You update i to 2. But L doesn't change because you didn't ask L[0] to be updated. As L includes numbers, when you do for i in L, then i is not the element of L itself, but a clone of it.

A proper way to do it would be :

for i in range(len(L)) :
    L[i] += 1 #you update L[i] itself this time

or if you like a more compact way :

L = [i+1 for i in L]

I hope I was clear enough. Have a nice day ;-)

6 Comments

"when you do for i in L, then i is not the element of L itself, but a clone of it." => wrong. Well, mostly wrong... What i points to IS the list's element, but rebinding the name i doesn't change the list. See nedbatchelder.com/text/names.html for a more in-depth explanation.
@brunodesthuilliers, thx! i agree with you
Oh BTW, your last "proper way" doesn't do the same thing as what the OP asks for - it rebinds L but does NOT change the list L was pointing to, so other references to this original list will remain unchanged. You want L[:] = [i+1 for i in L] to have the same behaviour (update the list in place).
@Kwikerr You really need to study Ned's article. Also see python.net/~goodger/projects/pycon/2007/idiomatic/…
@Kwikerr in this case the augmented assignment operator is overriden to also execute a list.extend() operation and return the LHS list - so you actually have both a rebind operation (that by itself doesn't change L) AND a mutation of the list i is pointing to. Replace i += [1] with i.extend([1]) and you'll have the real behaviour. If you really want to understand python's "variables" you have to totally forget the traditional C/Pascal/etc definition of "variable" (where a variable is a memory address) and think in terms of "names" and "bindings".
|
-1
for i in L:

This means while iterating over the list, value of each element in list is stored in i.

So if you change the value of i no change will happen in the list

Consider this-

a=2
b=a
b=3

Changing b does not change the value of a.

3 Comments

Thank you! I understand this, but this is for integer variable. Integer can't be changed originally. But List can get changed.
Can you explain what do you mean by Integer can't be changed originally?
@KeshavBansal python integers are immutable, lists are mutable. And stating that "element in list is stored in i" is misleading at best and actually plain wrong from a technical POV - "i" is just a name, not a memory address, so nothing is "stored in" it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.