[Python-Dev] "is", "==", and sameness
Gordon McMillan
gmcm@hypernet.com
Fri, 12 May 2000 18:05:46 -0400
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
1
>>> 100 + 3 is 101 + 2
0
>>>
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:
>
> 1. 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:
>>> sys.getrefcount(None)
167
>>>
> 2. After Point(3.0,4.0) is evaluated, its attributes will not be
> changed.
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.
- Gordon