What is the correct way to define __hash__?

Robert Kern robert.kern at gmail.com
Mon Oct 12 18:29:36 EDT 2009


On 2009-10-12 17:12 PM, Peng Yu wrote:
> On Mon, Oct 12, 2009 at 4:03 PM, Robert Kern<robert.kern at gmail.com>  wrote:
>> On 2009-10-12 15:45 PM, Peng Yu wrote:
>>>
>>> Hi,
>>>
>>> I'm wondering what is the general way to define __hash__. I could add
>>> up all the members. But I am wondering if this would cause a
>>> performance issue for certain classes.
>>
>> Unless if you are very familiar with the math of hash functions, I don't
>> recommend that you try to implement one directly. Instead, make a tuple of
>> the hashable content of your class and return the result of calling hash()
>> on that tuple. Be sure to make your equality comparison do the right thing.
>>
>> class A(object):
>>   def __init__(self, a, b):
>>     self.a = a
>>     self.b = b
>>
>>   def _key(self):
>>     # I include the name of the class so as to differentiate between other
>>     # classes that might also have a _key() method. If you have several
>> classes
>>     # or subclasses that are allowed to compare equal to each other, use some
>>     # other common string here.
>>     return (type(self).__name__, a, b)
>>
>>   def __hash__(self):
>>     return hash(self._key())
>>
>>   # Coincidentally, the _key() method can usually be reused for comparisons.
>>   # I recommend doing this for the equality comparisons, at least, when you
>> can
>>   # because of the requirement that two items that compare equal must have
>> the
>>   # same hash value.
>>   def __eq__(self, other):
>>     return self._key() == other._key()
>>
>>   def __ne__(self, other):
>>     return not (self == other)
>>
>>   ...
>
> Do I need to define other 4 comparison operators besides __eq__ and __ne__?

Yes. There are recipes to fill in the rest if you just provide __eq__ and __lt__:

   http://code.activestate.com/recipes/576685/

Or you could continue to use the __cmp__ method, but it will be going away in 
Python 3.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco




More information about the Python-list mailing list