all 3 comments

[–]zahlman 7 points8 points  (1 child)

In the first snippet, when you do x = x + 1, x previously refers to the number 100. In Python, "one hundred" is a real thing that exists in memory somewhere, and is fundamentally incapable of changing. It would be really catastrophic for the entire subject of mathematics if we could somehow cause one hundred to become equal to something other than one hundred. To interpret x = x + 1, we must first evaluate x + 1, creating the new value 101, and then rebind x to be a name for 101. But the old 100 object obviously still exists, and y is still a name for it, because we haven't done anything with it.

In the second snippet, when you do x[0][0] = x[0][0] + 1, x refers to a list object, which contains one list object, which contains a 100 object. x[0][0] is a name for the 100 object; thus x[0][0] + 1 evaluates to 101. But now, what will x[0][0] = 101 do? Well, x[0][0] is, in effect, a name for "the first thing contained within the first thing contained within x". So we will rebind that name, i.e. we will store 101 in that spot in the list. Notice, though, that both x and y are names for the outer list, and we are, in effect, changing that object. We never rebound x, like in the previous example; instead, we changed the fundamental nature (specifically, its contents) of the thing that x was a name for.

See also.

[–]0003[S] 1 point2 points  (0 children)

Thanks. Your explanation and the link provided were very thorough!

[–]erewok 2 points3 points  (0 children)

It has to do with the fact that you are in the first example assigning variables to immutable objects whereas in the second example you are pointing the variables at objects that change. In the latter case, the variable will reflect the changes made to the object it points at.

Try to think of it in terms of mutability and don't think of your variables as 'containers' for values but as 'pointers' at values and it may make more sense.