Судя по вашему методу __hash__
, класс хранит ссылки на свои аргументы и использует их в качестве хэша. Проблема в том, что эти аргументы используются совместно с кодом, который сконструировал объект. Если они изменят аргумент, хеш изменится, и вы не сможете найти объект в каких-либо словарях, в которых он находился.
Аргументы не должны быть сложными, подойдет простой список.
In [13]: class Spam(object) :
....: def __init__(self, arg) :
....: self.arg = arg
....: def __hash__(self) :
....: return hash(tuple(self.arg,))
In [18]: l = range(5)
In [19]: spam = Spam(l)
In [20]: hash(spam)
Out[20]: -3958796579502723947
Если я изменю список, который передал в качестве аргумента, хеш изменится.
In [21]: l += [10]
In [22]: hash(spam)
Out[22]: -6439366262097674983
Поскольку ключи словаря организованы по хешу, когда я делаю x in d
, первое, что делает Python, - это вычисляет хеш x и ищет в словаре что-то с таким значением хеша. Проблема заключается в том, что когда хеш объекта изменяется после помещения в словарь, Python будет смотреть на новое значение хеша и не будет видеть там нужный ключ. Используя список ключей, вынуждает Python проверять каждый ключ на равенство, минуя проверку хеша.