stackoverflowuser2010
stackoverflowuser2010

Reputation: 41029

Custom class object and "in" set operator

I'm using Python 3.6. Suppose that I'm trying to keep a unique set of tuples. I know I can use tuple in set and get back the correct result (the set contains the tuple or not).

s = set()
t1 = (1, 2)
t2 = (1, 2)
s.add(t1)
print(t2 in s) # True -- Great!

Now, suppose I have a custom class that contains a tuple. I would like to define uniqueness for the custom class objects as uniqueness for the tuple. I did the following:

class TupleWrapper(object):

    def __init__(self, t):
        self.t = t # tuple

    def __hash__(self):
        return hash(self.t)


s = set()
t1 = TupleWrapper((1, 2))
s.add(t1)
t2 = TupleWrapper((1, 2))
print(t2 in s) # False -- WHY?

I wrote my own __hash__() method that hashes the tuple. So why are the two TupleWrapper objects with the same tuple not found to be the same in the set? Do I need to override another method?

Upvotes: 3

Views: 169

Answers (1)

acushner
acushner

Reputation: 9946

you need to implement __eq__ on TupleWrapper as well.

def __eq__(self, other):
    if isinstance(other, TupleWrapper):
        return self.t == other.t
    return NotImplemented

otherwise, when checking to see if the object is already in the set, it will default to identity comparison, which is just is (i.e., t1 is t2 or id(t1) == id(t2)).

more detail: loosely speaking, on insertion, set (and dict) first use the hash value to figure out which bucket things are in. then, in that bucket, it uses == to check, in the case of a hash collision, if that object is already there.

hash documentation here

Upvotes: 7

Related Questions