Mark Ransom answered on a SO question about hashes here in SO:
[...] An object is hashable if it has a hash value which never changes during its lifetime. So by the official definition, anything mutable can't be hashable, even if it has a
__hash__()
function. My statement about both requirements being necessary is untrue, because being hashable already implies the requirement to be immutable.
I want to make sure, that I got that right - even as a non native speaker - so I hope someone corrects me if I got it wrong.
Assuming this class
class Author(object):
def __init__(self, id, name, age):
self.id = id
self.name = name
self.age = age
def __eq__(self, other):
return self.id==other.id\
and self.name==other.name
def __hash__(self):
return hash(('id', self.id,
'name', self.name))
I understand, that __eq__
allows me to compare objects of this class with the ==
operator. From Marks answer I understand, that even if my object peter = Author(1, "Peter", 33)
has a __hash__
it is not hashable because I potentially could do something like peter.age = 43
which means it is not immutable. So my objects of the class Author
are not hashable and therefore not usable as keys in dictionarys for example? Did I get right or does it seem, that I need more explanation? :-)
Instances of this class are hashable if you promise never to reset
id
orname
on them. You can't guarantee that these attributes will never be reset, by the Python principle that "we are all consenting adults here", but it would be very bad style to offer methods that reset the attributes that__hash__
relies on.E.g., if you offer a
set_name
method on instances ofAuthor
, but noset_id
, then clients of the class can reasonably presume that__hash__
operates only on theid
.If you want to make it clear to clients of
Author
that they should not reset some attribute, you can label it private by prepending an_
to its name. If you then still want to offer (read-only) access to the attribute using its common name, you can make it a property: