Equality is not always sufficient
I’ve just got hit by one of really typical errors while writing simple value type in Python. Consider following code:
class Simple(object):
def __init__(self, val):
self.val = val
def __eq__(self, other):
return self.val == other.val
The class Simple overrides equality operator delegating it to it’s value. Seems dead simple and easy for the first time. But not quite so. What will following snippet print?
a, b = Simple(3), Simple(3)
set_a, set_b = set([a]), set([b])
print 'a == b: ', a == b
print 'set_a == set_b', set_a == set_b
You’ve guessed it: True, False. This is because two sets may be equal only if all elements hashes are equal. So I thought I will fix it with this:
class Hashimple(object):
def __init__(self, val):
self.val = val
def __eq__(self, other):
return self.val == other.val
def __hash__(self):
return (self.val * 5) + 7
Seems better, but look at this snippet and guess once more:
a, b = Hashimple(3), Hashimple(3)
set_a, set_b = set([a]), set([b])
print 'Hashimple'
print 'a == b: ', a == b
print 'set_a == set_b', set_a == set_b
print 'a != b', a != b
True, True, True?!? Well, Python will not imply that a != b , not even when a == b.
This bug has been made thousands times by thousands of coders, it occurs not only in Python, but also in various other languages (Java, Ruby), it’s been described in lots of books, but I just keep forgetting about it. Maybe writing a blog post will help me remember?
Comments(0)