I found an interesting observation lately, that there are things to impact the hashability of an object/instance of a class. And I am wondering how and why?
For example, I got a linked list class called ListNode:
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def __repr__(self):
if self.next:
return "{}->{}".format(self.val, repr(self.next))
else:
return "{}".format(self.val)
# def __eq__(self, other):
# if not self and not other:
# return True
# elif not self or not other:
# return False
# else:
# return self.val == other.val and self.next == other.next
# def __eq__(self, other):
# return str(self) == str(other)
Notice that I blocked the __eq__ method.
Now if I create an instance:
A = ListNode(1)
B = ListNode(2)
C = ListNode(3)
A.next = B
B.next = C
print(hash(A))
Then it is hashable, however, I do get different output number everytime I run it.
Now if I unblock the __eq__ method, all of sudden it is not hashable anymore. Why?
It seems that the hash method will use __eq__. And how does it know it is not hashable after __eq__ is enabled?
Additional:
If I write the __eq__ method to just compare the str version of the two linked list (the second __eq__ method), I thought this could solve the problem, because by converting the linked list into a string, it becomes an hashable data, but I still get the unhashable error message
Thanks!
According to @juanpa.arrivillaga's comment:
__eq__ will remove the default __hash__ method, making it unhashable.
So I added my own__hash__ mehtod:
def __hash__(self):
return hash(id(self))
This solved the problem and made ListNode hashable again with __eq__ enabled.