Custom hash: is object in a dictionary?

I’d like to check if my object is already present in a dictionary based on it’s name. My current implementation does not return expected results, so for sure I am missing something here.

My class:

@dataclass
class Foo:
    name: str
    number: int
        
    def __hash__(self):
        return hash(self.name)

and the code:

d = {}
foo1 = Foo('foo1', 1)
foo2 = Foo('foo2', 2)
foo3 = Foo('foo1', 3)
foo4 = Foo('foo4', 1)
d[foo1] = foo1
d[foo2] = foo2

print(f'Is foo3 in d? {foo3 in d}') # prints: "Is foo3 in d? False" Expected True (NOK)
print(f'Is foo4 in d? {foo4 in d}') # prints: "Is foo4 in d? False" Expected False (OK)
print(f'foo1 hash: {foo1.__hash__()}') # 4971911885166104854
print(f'foo3 hash: {foo1.__hash__()}') # 4971911885166104854

Do I need anything else than the __hash__() implementation?

Answer

You need to add the equality dunder also. From the documentation of __hash__ and __eq__:

If a class does not define an eq() method it should not define a hash() operation either;

After I add the __eq__, I get the following behavior.

    def __eq__(self, x):
        return hash(self) == hash(x)

On running the program, I get:

Is foo3 in d? True
Is foo4 in d? False
foo1 hash: -4460692046661292337
foo3 hash: -4460692046661292337