hashing mutable instances

Michael Hudson mwh at python.net
Thu Oct 30 10:14:34 EST 2003


Bernhard Herzog <bh at intevation.de> writes:

> Michael Hudson <mwh at python.net> writes:
> 
> > Bernhard Herzog <bh at intevation.de> writes:
> >
> >> IMO it depends on what equality means for instances. E.g. if two
> >> instances are only equal if they're identical, i.e. a == b is equivalent
> >> to a is b, then defining __hash__ can be very useful, because then you
> >> can use them in dictionaries and mutability doesn't really matter
> >> because no change to one instance can make it equal to a nother
> >> instance.
> >
> > Um.  In that case why define __hash__ or __eq__ at all?
> 
> Good question. I didn't know that that was the default implementation of
> __hash__. It's not documented AFAICT, but it does seem to be the case. I
> wonder why, even though it's useful.

Well, I didn't so much know that this was the default implementation
of __hash__ as know that instances of classes that don't do anything
to the contrary compare equal iff identical and are usefully hashable.

(Python Mystery Theatre question: for such a class, when can you have
id(ob) != hash(ob)?)

> The language reference for __hash__ says:
> 
>    If a class does not define a __cmp__() method it should not define a
>    __hash__() operation either;
> 
> Seems a bit outdated in that it only mentions __cmp__ here and not
> __eq__ as well as it does right after the semicolon, but that would not
> indicate to me that hash works for an instance without a hash method.

I hadn't had the distraction of reading this section of the language
reference :-) Did you seriously think that you *had* to define
__hash__ to make instances of your classes hashable?

> Of course the sentence above could be taken to mean that if you
> define neither method the defaults to the right thing, but that
> would seem very obscure to me.

Well, this is Python after all.  I would have read

    if it defines __cmp__() or __eq__() but not __hash__(), its
    instances will not be usable as dictionary keys.

to imply that in other situations that instances would be usable as
dictionary keys.

> Anyway, I've found that if you end up comparing objects very often
> is can be a substantial performance gain if you do define __eq__
> even though it ends up doing the same as the default comparison. At
> least for old style classes when __eq__ is not defined python tries
> __cmp__ and __coerce__ and __getattr__ if defined is called for all
> of them.

Old-style classes?  What are they? :-) Didn't know about that.

> Then, once you have defined __eq__ you also need to have __hash__ if you
> want your objects to be hashable.

Yes.  I'm glad that bit of silliness is now dead (ish).

Cheers,
mwh

-- 
  We've had a lot of problems going from glibc 2.0 to glibc 2.1.
  People claim binary compatibility.  Except for functions they
  don't like.                       -- Peter Van Eynde, comp.lang.lisp




More information about the Python-list mailing list