Archive for November, 2009

Equality is not always sufficient 0

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?

Docs: __eq__, __hash__