6 Answers
6

The reason that this doesn't work is because you're misunderstanding what elemis. It's not the object itself, and it's not even correct to call it a "variable".

It's a name, kind of like a label, that points to the object. If you just directly assign over it, you're just overwriting the name to point at something else. But, you still have the original reference to the list, so assigning a different value over elem doesn't modify lis itself.

Now, in this case, since all of the objects that elem points to are integers, you can't even change them at all - because integers (and many other types, like strings or tuples) are immutable. That means, simply put, that once the object has been created it cannot be modified. It has nothing to do with whether they "have methods" or not (all Python objects have methods, integers included), but on whether or not they are immutable.

Some objects, however, are mutable, meaning that they can be changed. Lists are examples of such objects. In your second example, elem is a name that references the list objects contained within lis, which themselves are mutable. That is why modifying them in-place (using .append(), or .remove(), etc) works fine.

But, you still have the original reference to the list, so it doesn't modify that. Note: for elem in lis: lis = 3 will still work, even if you change the original reference to the list because the for in ... expression is evaluated first.
–
jamylakAug 2 '12 at 21:15

@jamylak: Yes, but after the loop is over, lis is be clobbered. Since you have no more references pointing to the list object, it'll be gobbled up by the garbage collector.
–
voithosAug 2 '12 at 21:32

my problem is that part isn't very clear imo. Just by having an original reference to the list doesn't mean you can't modify it. eg. you can mutate that original reference itself. What do you mean by that whole sentence?
–
jamylakAug 2 '12 at 21:35

The elem variable in your for loop is a reference to the current object on each iteration. Changing it won't do anything; it will just change the value of the variable elem and that's going to be changed the next time through the loop anyway. To actually change the value of the element in the list, you need a reference to the list and the index of the element to be changed, and you don't have the latter.

So what you want to do is something like this:

for index, elem in enumerate(lis):
lis[index] = 3

This way you have elem for the element's value and index for the position in the list. It saves you from writing lis[index] constantly to get values, but you must still do so to change elements.

You can also do:

for index in xrange(len(lis)):
lis[index] = 3

However, in most situations this is considered un-Pythonic (among other things, what happens if the list gets longer or shorter while it's being iterated)?

Here, you are actually modifying the list object in your second example. In the first example, you are not modifying the number, you are replacing it. This can be a complicated nuance for new users of Python.

Check this out:

>>> x = 1
>>> id(x)
4351668456
>>> x = 2
>>> id(x)
4351668432

id returns the identifier of the object. As you can see above, the object of x changes both of these times.

>>> y = [1]
>>> id(y)
4353094216
>>> y.append(2)
>>> id(y)
4353094216

Here, I modify the list, so the list is still the original object y.

So, all this means that when you are doing elem = 3, it's not modifying it, it is replacing it. And by now, it's not associated with the list anymore.

This is one of the ways you could do what you are trying to do. This grabs the index and then modifies the list, not the number.

In your first example you are trying to modify an integer, and it's inmutable (as strings are).

Python variables should be seen as labels pointing to an object. When you iterate over a list of inmutables, elem points to an inmutable object, not to that position in the list, so you can't modify the original list.

In the second case, elem point to an object that can be modified, so you see the original list changed.

Not very clear, elem = 3 still won't work on list objects.
–
jamylakAug 2 '12 at 21:10

No, but it does work in his first case. I don't get the sense that he's wanting to assign a value to a list. He's wondering why elem = 3 doesn't modify the list in place.
–
brian buckAug 2 '12 at 21:16

You've said that the type of the element will denote whether you can do elem = 3 which won't work either way. The actual difference is that the second case mutates the object instead of binding the name elem to 3 in the local namespace.
–
jamylakAug 2 '12 at 21:21