dictionary mutability, hashability, __eq__, __hash__

Jussi Piitulainen jussi.piitulainen at helsinki.fi
Sun Nov 27 07:14:55 EST 2016


Veek M writes:

[snip]

> Also if one can do x.a = 10 or 20 or whatever, and the class instance
> is mutable, then why do books keep stating that keys need to be
> immutable?  After all, __hash__ is the guy doing all the work and
> maintaining consistency for us. One could do:
>
> class Fruit:
>   editable_value = ''
> def __hash__(self):
>  if 'apple' in self.value: 
>    return 10
>  elif 'banana' in self.value:
>    return 20
>
>
>  and use 'apple' 'bannana' as keys for whatever mutable data..
> Are the books wrong?

The hash does not do all the work, and the underlying implementation of
a dictionary does not react appropriately to a key changing its hash
value. You could experiment further to see for yourself.

Here's a demonstration that Python's dictionary retains both keys after
they are mutated so that they become equal, yet finds neither key
(because they are not physically where their new hash value indicates).

I edited your class so that its methods manipulate an attribute that it
actually has, all hash values are integers, constructor takes an initial
value, objects are equal if their values are equal, and the written
representation of an object shows the value (I forgot quotes).

test = { Fruit('apple') : 'one', Fruit('orange') : 'two' }

print(test)
print(test[Fruit('orange')])
# prints:
# {Fruit(apple): 'one', Fruit(orange): 'two'}
# two

for key in test: key.value = 'banana'

print(test)
print(test[Fruit('banana')])

# prints:
# {Fruit(banana): 'one', Fruit(banana): 'two'}
# Traceback (most recent call last):
#   File "hash.py", line 25, in <module>
#     print(test[Fruit('banana')])
# KeyError: Fruit(banana)



More information about the Python-list mailing list