I am trying to implement the hash definition suggested here but I am getting an error when trying to use hash on the class. The class is defined as so:
class Metabolite:
def __init__(self, name_in='', id_in='', synonyms_in=[], InChIKey_in='', formulae_in=[], charge_in='', ecs_in=[], mtk_in = [], mtb_in = '', mtm_in = '', mts_in = '', bkm_id_in = '', source_in = ''):
self.name = name_in
self.id = id_in
self.formulae = formulae_in
self.inchikey = InChIKey_in
self.synonyms = synonyms_in
self.charge = charge_in
self.ecs = ecs_in
self.mtb = mtb_in
self.mtk = mtk_in
self.mtm = mtm_in
self.mts = mts_in
self.bkm_id = bkm_id_in
self.source = source_in
def key(self):
return self.id, self.inchikey, self.mts, self.mtk, self.mtb, self.mtk
def __key(self):
return tuple([self.id, self.inchikey, self.mts, self.mtk, self.mtb, self.mtk])
def __eq__(self, other):
return self.__key() == other.__key()
def __hash__(self):
return hash(tuple(self.__key()))
However on creating an instance of this class and asking for a hash I get the following:
>>> met = Metabolite('this_metabolite', '10002', 'AADBRHFDG')
>>> hash(met)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-7941e6f25128> in <module>()
----> 1 hash(met)
classes.py in __hash__(self)
27
28 def __hash__(self):
---> 29 return hash(tuple(self.__key()))
30
31
TypeError: unhashable type: 'list'
despite my desperate attempts in the class definition to force the type to be a (hashable) tuple. I am new to classes in Python, any help would be greatly appreciated.
When run in IDLE, the error comes up as:
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
hash(met)
File "<string>", line 27, in __hash__
TypeError: unhashable type: 'list'
SOLVED: thanks to those who responded.
A tuple containing an empty list will not work:
>>> my_tuple = tuple(('a',[]))
>>> type(my_tuple)
tuple
>>> hash(my_tuple)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-28-f63af41cc75b> in <module>()
----> 1 hash(my_tuple)
TypeError: unhashable type: 'list'
so I had to create a list of my variables before returning them in __key():
def __key(self):
key_list = []
key_list.append(self.id)
key_list.append(self.inchikey)
key_list.append(self.mts)
key_list.append(self.mtb)
for entry in self.mtk:
key_list.append(entry)
return tuple(key_list)
The problem is that the
mtkattribute is a list (by default). Mutable sequence types cannot be hashed and since your key containsmtk(twice), the key is not hashable (even if the key itself is atuple).If you modify your key generation as follows, then it becomes hashable (but it might prove seriously inefficient):
This returns in Python 2.7 (code pasted from your question with above modification):