Greg Weeks wrote:
From the Python Reference Manual [emphasis added]:
Types affect almost all aspects of object behavior. Even the importance of object IDENTITY is affected in some sense: for immutable types, operations that compute new values may actually return a reference to any existing object with the same type and value, while for mutable objects this is not allowed.
This seems to be saying that two immutable objects are (in some sense) the same iff they have the same type and value, while two mutable objects are the same iff they have the same id(). I heartily agree, and I think that this notion of sameness is the single most useful variant of the "equals" relation.
Notice the "may" in the reference text.
88 + 11 is 98 + 1
100 + 3 is 101 + 2
Python goes to the effort of keeping singleton instances of the integers less than 100. In certain situations, a similar effort is invested in strings. But it is by no means the general case, and (unless you've got a solution) it would be expensive to make it so.
Indeed, I think it worthwhile to consider modifying the "is" operator to compute this notion of sameness. (This would break only exceedingly strange user code.) "is" would then be the natural comparator of dictionary keys, which could then be any object.
The implications don't follow. The restriction that dictionary keys be immutable is not because of the comparison method. It's the principle of "least surprise". Use a mutable object as a dict key. Now mutate the object. Now the key / value pair in the dictionary is inaccessible. That is, there is some pair (k,v) in dict.items() where dict[k] does not yield v.
The usefulness of this idea is limited by the absence of user-definable immutable instances. It might be nice to be able to declare a class -- eg, Point -- to be have immutable instances. This declaration would promise that:
- When the expression Point(3.0,4.0) is evaluated, its
reference count will be zero.
That's a big change from the way Python works:
- After Point(3.0,4.0) is evaluated, its attributes will not be
You can make an instance effectively immutable (by messing with __setattr__). You can override __hash__ to return something suitable (eg, hash(id(self))), and then use an instance as a dict key. You don't even need to do the first to do the latter.