How to Make a Python Class Hashable with __eq__ and __hash__

Define __eq__ and __hash__ together on a Python class so equal instances share the same hash and work correctly in sets and dictionary keys.

Easy Python 3.9+ Aug 9, 2026 OOP & classes 13 views 0 copies

Python code

32 lines
Python 3.9+
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return self.x == other.x and self.y == other.y

    def __hash__(self):
        return hash((self.x, self.y))

    def __repr__(self):
        return f"Point({self.x}, {self.y})"


if __name__ == "__main__":
    p1 = Point(1, 2)
    p2 = Point(1, 2)
    p3 = Point(3, 4)

    print(f"p1 == p2: {p1 == p2}")
    print(f"p1 == p3: {p1 == p3}")
    print(f"hash(p1) == hash(p2): {hash(p1) == hash(p2)}")

    points_set = {p1, p2, p3}
    print(f"Set size (duplicates removed): {len(points_set)}")
    print(f"Points in set: {points_set}")

    lookup = Point(1, 2) in points_set
    print(f"Point(1, 2) in set: {lookup}")

Output

stdout
p1 == p2: True
p1 == p3: False
hash(p1) == hash(p2): True
Set size (duplicates removed): 2
Points in set: {Point(3, 4), Point(1, 2)}
Point(1, 2) in set: True

How it works

Python requires that objects which compare equal (eq) also return the same hash value (hash). The hash method here builds a tuple of the x and y attributes and passes it to the built-in hash() function. This guarantees that two equal Point instances produce identical hashes, satisfying the hash invariant. The repr method makes instances print in a readable way when the set is displayed. Because both methods are defined together, Point objects work correctly as set members and dictionary keys.

Common mistakes

  • Defining __eq__ without __hash__, which sets __hash__ to None and makes the class unhashable
  • Returning NotImplemented instead of False when other is not a Point, which breaks symmetic equality checks
  • Mutating x or y after the object is added to a set, corrupting its stored hash

Variations

  1. Use a dataclass with frozen=True, which auto-generates __eq__ and __hash__
  2. Store immutable attributes and skip setter methods to guarantee hash stability

Real-world use cases

  • Storing unique geometry points in a set to deduplicate graph nodes from sensor data.
  • Using dataclass-like entities as dictionary keys for caching precomputed results in a computation engine.
  • Placing value objects into sets for fast membership checks in a trading order matching system.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from OOP & classes

Related tutorials and quizzes for this topic.