Can’t modify list elements in a loop

While looping over a list in Python, I was unable to modify the elements without a list comprehension.
For reference:

li = ["spam", "eggs"]
for i in li:
    i = "foo"

li
["spam", "eggs"]

li = ["foo" for i in li]
li 
["foo", "foo"]

So, why can’t I modify elements through a loop in Python? There’s definitely something I’m missing, but I don’t know what. I’m sure this is a duplicate, but I couldn’t find a question about this, and if there is a link, that would be more than enough.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Because the way for i in li works is something like this:

for idx in range(len(li)):
    i = li[idx]
    i = 'foo'

So if you assign anything to i, it won’t affect li[idx].

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

for idx in range(len(li)):
    li[idx] = 'foo'

or use enumerate:

for idx, item in enumerate(li):
    li[idx] = 'foo'

Method 2

In fact with list comprehension you are not modifying the list, you are creating a new list and then assigning it to the variable that contained the previous one.

Anyway, when you do for i in li you are getting a copy of each value of li in variable i, you don’t get the reference to a position in li, so you are not modifying any value in li.

If you want to modify your list you can do it with enumerate:

>>> li = ["spam", "eggs"]
>>> for i,_ in enumerate(li):
        li[i] = "foo"
>>> li
 ['foo', 'foo']

or with xrange (in Python 2.7, use range in python 3):

>>> for i in xrange(len(li)):
        li[i] = "foo"
>>> li 
 ['foo', 'foo']

or with the list comprehension you showed in your question.

Method 3

I’m able to modify a list while looping:

lst = range(10)  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

for i, elem in enumerate(lst):
    lst[i] = 0   // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Method 4

for element in li – returns you a copy of element, not the element itself.

Solution for your case would be:

for i in range(len(li)):
    li[i] = 'foo'

Method 5

Maybe using dictionaries might be helpful.

>>> li = {0: "spam", 1:"eggs"}
    for k, v in li.iteritems():
        li[k] = "foo"

>>> li
{0: 'foo', 1: 'foo'}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x