0

I wanted to have a nice set all list elements to a default value function. The one I came up with doesn't work, but my second solution does. Can anyone tell me why it works one way but not the other?

First solution:

def set_all(the_list,value): #NOT doing anything
    for item in the_list:
        item = value

Second solution:

def set_all(the_list,value): #working as intended
    for i,item in enumerate(the_list):
        the_list[i] = value
Wurstbro
  • 974
  • 1
  • 9
  • 21
  • See http://stackoverflow.com/q/575196/395760 - I don't think it's an exact duplicate, but it's certainly highly related. –  Sep 28 '13 at 17:07

3 Answers3

5

When you do:

for item in the_list:
    item = value

You're only re-assigning the name item to something else (value, specifically), but you are not touching the reference the_list[i] that the list has to the original item.

Consequently, you don't actually touch the list, so it doesn't change.


You can look at it that way:

When you do for item in the_list, you create a new reference to the underlying object: item.

When you do item = value, you're changing that reference and pointing it to something else. But the other reference, the one the list has to the underlying object, remains unchanged.

Of course, when you do the_list[i], you're actually changing that reference that the list has to the object, which is why it works.

Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • So when I iterate, is `item` the copy of `the_list[x]` ? Therefore only useful for reading data, not changing/writing it? – Wurstbro Sep 28 '13 at 17:21
  • @Wurstbro Not, it's not a copy. There are no variables properly speaking in Python. There are only names that point to underlying objects. When you do `item.some_method()`, you may alter the object (e.g. if `item` was a `list` and you called `append`), and all the names that point to that object will see an object that has been modified. However, when you **change a name** by reassigning it, you do not change the underlying object, nor the other references that exist to it. – Thomas Orozco Sep 28 '13 at 17:25
  • Can I say that `item` pointed to `the_list[x]`, then points to `value`? – Wurstbro Sep 28 '13 at 17:26
  • @Wurstbro Those are both references to the same underlying object, but they don't share anything. – Thomas Orozco Sep 28 '13 at 17:28
2

In the first loop, item is a reference to the item from the list, not to a slot in the list. Changing it doesn't change the list.

To change the list you need to know what slot you're dealing with, which is what you're doing in the second case.

kindall
  • 178,883
  • 35
  • 278
  • 309
0

why not use this? its easier

the_list = [default_value]*len(the_list)
Foo Bar User
  • 2,401
  • 3
  • 20
  • 26
  • Well, it doesn't mutate the list but creates a new one, which is important if there are other references. But in any case, this wasn't the question - the question is only "Why does the first not work (but the second does)"? –  Sep 28 '13 at 17:08
  • I needed a way to alter all values in existing lists – Wurstbro Sep 28 '13 at 17:11
  • yeah makes sense, i thought if you didnt mind making a new one it would be a cleaner solution. – Foo Bar User Sep 28 '13 at 17:12