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