Reputation: 41029
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
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