hash values and equality

Ethan Furman ethan at stoneleaf.us
Fri May 20 13:56:02 EDT 2011


Chris Rebert wrote:
> On Thu, May 19, 2011 at 10:43 PM, Ethan Furman <ethan at stoneleaf.us> wrote:
>> Several folk have said that objects that compare equal must hash equal, and
>> the docs also state this
>> http://docs.python.org/dev/reference/datamodel.html#object.__hash__
>>
>> I'm hoping somebody can tell me what horrible thing will happen if this
>> isn't the case?  Here's a toy example of a class I'm thinking of writing
>> that will compare equal with int's, but hash differently:
> 
> This is the part considered "horrible":
>> --> d
>> {<Wierd object at 0x00BFE870>: '3',
>>  1: '1.0',
>>  2: '2.0',
>>  3: '3.0',
>>  <Wierd object at 0x00BFE830>: '2',
>>  <Wierd object at 0x00BFE710>: '1'}
> 
> Compare:
>>>> x = {5.0 : 'foo'}
>>>> x[5]
> 'foo'
> 
> Here's a more common/plausible "horrible" case closer to what the docs
> writers had in mind:
>--> class Naughty(object):
> ...     def __init__(self, n):
> ...         self.n = n
> ...     def __eq__(self, other):
> ...         return self.n == other.n
> ...
>--> Naughty(5) == Naughty(5)
> True
>--> Naughty(5) is Naughty(5)
> False
>--> bad = Naughty(3)
>--> y = {bad : 'foo'}
>--> y[bad] # just happens to work
> 'foo'
>--> del bad
>--> # ok, how do we get to 'foo' now?
>--> y[Naughty(3)] # try the obvious way
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> KeyError: <__main__.Naughty object at 0x2a1cb0>
>--> # We're screwed.
> 
> Naughty instances (and similar) can't be used sensibly as hash keys
> (unless you /only/ care about object identity; this is often not the
> case).

I tried this sequence (using Python 3, BTW -- forgot to mention that 
little tidbit -- sorry!):

--> del two
--> two
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
NameError: name 'two' is not defined
--> d
{<__main__.Wierd object at 0x00C0C950>: '3',
  1: '1.0',
  2: '2.0',
  3: '3.0',
  <__main__.Wierd object at 0x00B3AC10>: '2',
  <__main__.Wierd object at 0x00B32E90>: '1'}
--> new_two = Wierd(2)
--> d[new_two]
'2'

~Ethan~



More information about the Python-list mailing list