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.