What is the correct way to define __hash__?

Chris Rebert clp2 at rebertia.com
Tue Oct 13 00:20:43 CEST 2009


On Mon, Oct 12, 2009 at 3:12 PM, Peng Yu <pengyu.ut at gmail.com> 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__?

No; dictionaries are unordered and thus don't utilize the non-equality
comparison operators.

Cheers,
Chris
--
http://blog.rebertia.com



More information about the Python-list mailing list