Mutation

From 6.034 Wiki

Jump to: navigation, search

A conversation about mutation in Python:

I was playing around with "is" today and found that it doesn't work for lists. Could you explain why? Thank you very much.
>>> l = [1,2,3,4]
>>> l
[1, 2, 3, 4]
>>> l is [1,2,3,4]
False
>>> l is [1, 2, 3, 4]
False
>>> l == [1,2,3,4]
True
Excellent question. The is operator is telling the truth -- those lists are not the same lists even though they have the same contents (for now).
Consider:
>>> a = [1,2,3]
>>> b = [1,2,3]
>>> c = a
>>> a is b
False
>>> a == b
True
>>> a is c
True
>>> a[1] = 12
>>> a
[1,12,3]
>>> b
[1,2,3]
>>> c
[1,12,3]
So c=a is pointed to a's contents when a is a list.? However c=a is pointed to a new copy of the content when a is a number or a string?
How do we know if something is set to another thing that it is going to be the same thing or a copy made?

The assignment (=) is doing the same thing in both cases. The difference is that 5 is always the same value, and "hi" is always the same value, whereas brackets [] construct new lists. Those lists, in turn, then point to other values. To make that clear,

>>> 5 is 5
True
>>> "hi" is "hi"
True
>>> [] is []
False
>>> 

How do you know which kind is which? There is no way to know for sure in general, even with the is operator. As you design individual classes, you can make either choice. That said, immutable things (things whose value cannot change) like numbers and strings will generally have == and is agree, whereas for mutable things like lists and dictionaries, that must not be the case.

Consider what would happen if a mutable thing did return the very same object from its empty constructor:

>>> a = []
>>> b = []
>>> a.append(3)
>>> b
[3]
!!!  If that were true, it would be very confusing indeed!

On the other hand, there is nothing useful in having lots of different identical objects which are all the integer 5. Because 5's value cannot change, it's safe for everyone to refer to the very same object.

Look at the "aliasing" part of the gotchas file -- sorry that we didn't get to it in Friday's megarecitation. Accidental aliasing, that is to say, having two names accidentally point to the same mutable object instead of a copy of that object, is a common mistake. It allows some piece of data to change where the programmer didn't expect a change to be possible.

The new classes you create will, by default, be the mutable kind, which means you will have to be aware of aliasing, and be careful to copy the objects where needed. See, for example, the __init__ method for the NdPoint class.

See also, http://en.wikipedia.org/wiki/Immutable_object

Personal tools