hashing mutable instances

Alex Martelli aleax at aleax.it
Thu Oct 30 09:41:17 EST 2003


Bernhard Herzog wrote:
   ...
> 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

I don't know why the official docs don't mention this fact -- I do
mention it in "Python in a Nutshell", of course (p. 132).

> wonder why, even though it's useful.

The reason this is done is because it's useful.

> 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.

Yes, but making your classes newstyle would be a MUCH greater performance
boost in this situation.  See:

[alex at lancelot bo]$ timeit.py -c -s'class X:pass' -s'x=X()' 'x==None'
100000 loops, best of 3: 3.5 usec per loop
[alex at lancelot bo]$ timeit.py -c -s'class X:
>   def __eq__(self, other): return id(self)==id(other)' -s'x=X()' 'x==None'
100000 loops, best of 3: 2.1 usec per loop

[alex at lancelot bo]$ timeit.py -c -s'class X(object):pass' -s'x=X()'
'x==None'
1000000 loops, best of 3: 0.42 usec per loop
[alex at lancelot bo]$ timeit.py -c -s'class X(object):
  def __eq__(self, other): return id(self)==id(other)' -s'x=X()' 'x==None'
100000 loops, best of 3: 2.1 usec per loop

Instead of saving 40% of the comparison time by defining __eq__, why not
save 80+% of it, instead, just by making the class newstyle?  Note that
the comparison time is avoud equal for both old and new style classes if
you do define an __eq__ -- but while it's a 40% speedup for oldstyle
ones, it's a slowdown by 5 times for newstyle ones.


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

Another good performance reason to make the class newstyle and thus
avoid having to define __eq__, IMHO.

These days the only casee where I use oldstyle classes (except in Q&D
scripts where I simply forget to say '(object)', but that's getting
rare as the good habit becomes ingrained:-) is for exception classes,
which (for reasons that escape me) ARE supposed to be oldstyle.  The
exception that proves the rule?-)


Alex





More information about the Python-list mailing list