[Python-Dev] Why should the default hash(x) == id(x)?

Josiah Carlson jcarlson at uci.edu
Wed Nov 2 18:46:09 CET 2005

Noam Raphael <noamraph at gmail.com> wrote:
> Hello,
> While writing my PEP about unifying mutable and immutable, I came upon this:
> Is there a reason why the default __hash__ method returns the id of the objects?

A quick search in the list archives via google search
    "site:mail.python.org object __hash__"
Says that Guido wanted to remove the default __hash__ method for object
in Python 2.4, but that never actually happened.


There may be more code which relies on the default behavior now, but
fixing such things is easy.

> Now, I just thought of a possible answer: "because he wants to store
> in his dict both normal objects and objects of his user-defined type,
> which turn out to be not equal to any other object."

Which is a use-case, but a use-case which isn't always useful.  Great
for singleton/default arguments that no one should ever pass, not quite
so good when you need the /original key/ (no copies) in order to get at
a value in a dictionary - but that could be something that someone wants.

> This leads me to another question: why should the default __eq__
> method be the same as "is"? If someone wants to check if two objects
> are the same object, that's what the "is" operator is for. Why not
> make the default __eq__ really compare the objects, that is, their
> dicts and their slot-members?

Using 'is' makes sense when the default hash is id (and actually in
certain other cases as well). Actually comparing the contents of an
object is certainly not desireable with the default hash, and probably
not desireable in the general case because equality doesn't always
depend on /all/ attributes of extension objects.

    Explicit is better than implicit.
    In the face of ambiguity, refuse the temptation to guess.

I believe the current behavior of __eq__ is more desireable than
comparing contents, as this may result in undesireable behavior
(recursive compares on large nested objects are now slow, which used to
be fast because default methods wouldn't cause a recursive comparison at

As for removing the default __hash__ for objects, I'm actually hovering
around a -0, if only because it is sometimes useful to generate unique
keys for dictionaries (which can be done right now with object() ), and
I acknowledge that it would be easy to subclass and use that instead.

 - Josiah

More information about the Python-Dev mailing list