__eq__
__eq__(self, other) bool · Added in vPython 2.1 · Updated March 18, 2026 · Dunder Methods Overview
The __eq__ method defines the behavior of the equality operator (==) for your class. By default, Python compares objects by identity (whether they are the same object in memory), which is the behavior for all user-defined classes unless you override __eq__.
Signature
def __eq__(self, other):
# Return True if self equals other, False otherwise
# Return NotImplemented to fall back to the other object's __eq__
Basic Example
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
if isinstance(other, Person):
return self.age == other.age
return False
john = Person("John", 30)
jane = Person("Jane", 30)
print(john == jane) # True - same age
# output: True
The __ne__ Method
The __ne__ method defines behavior for the not-equal operator (!=). In Python 3, if you define __eq__ but not __ne__, Python automatically derives __ne__ as the negation of __eq__.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
if isinstance(other, Point):
return self.x == other.x and self.y == other.y
return False
p1 = Point(1, 2)
p2 = Point(1, 2)
p3 = Point(3, 4)
print(p1 == p2) # True
# output: True
print(p1 != p3) # True
# output: True
Comparison Fallback Order
When Python evaluates a == b:
- First, Python tries
a.__eq__(b) - If that returns
NotImplemented, Python triesb.__eq__(a) - If both return
NotImplemented, objects are compared by identity
Returning NotImplemented tells Python to try the other object’s method:
class Money:
def __init__(self, amount):
self.amount = amount
def __eq__(self, other):
if isinstance(other, Money):
return self.amount == other.amount
return NotImplemented # Let other try
dollar = Money(100)
cents = Money(10000)
print(dollar == cents) # Depends on cents.__eq__
Important Gotchas
1. Always check the type
Never assume other has the same attributes:
# Wrong - will raise AttributeError
def __eq__(self, other):
return self.age == other.age # Fails if other has no age
# Correct - check type first
def __eq__(self, other):
if not isinstance(other, Person):
return False
return self.age == other.age
2. __eq__ and __hash__
This is intentional behavior by design, not a bug. If you override __eq__, Python sets __hash__ to None by default. This makes your objects unhashable (cannot be used in sets or as dictionary keys), which prevents inconsistent behavior when objects that compare equal have different hash values:
class Person:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return isinstance(other, Person) and self.name == other.name
# This will fail - Person is now unhashable
# person = Person("John")
# {person} # TypeError: unhashable type 'Person'
This happens because Python assumes that if two objects are equal, they should have the same hash value. By setting __hash__ to None, Python prevents you from accidentally violating this contract. To make objects hashable again, explicitly define __hash__:
class Person:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return isinstance(other, Person) and self.name == other.name
def __hash__(self):
return hash(self.name)
person = Person("John")
print({person}) # Works
# output: {<__main__.Person object at ...>}
3. Reflexive comparison
self == self should always return True. This works automatically in Python—you don’t need to handle it explicitly:
# This is always true in Python
print(5 == 5) # True
# output: True
Comparison with Different Types
Python allows comparing objects of different types:
class Wrapper:
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, Wrapper):
return self.value == other.value
if isinstance(other, (int, float)):
return self.value == other
return False
w = Wrapper(42)
print(w == 42) # True
# output: True
print(w == "hello") # False
# output: False
Return Values
The __eq__ method should return a boolean (True or False), or NotImplemented to indicate that the comparison is not handled. It should not raise exceptions under normal circumstances—return False instead when objects cannot be compared.
Summary
- Define
__eq__to customize equality comparison for your objects - Return
NotImplementedfor unsupported types to allow reverse comparison - If you define
__eq__without__hash__, objects become unhashable by design - Python 3 automatically derives
__ne__from__eq__if you don’t define it - Always check types before comparing attributes to avoid AttributeError
See Also
- hash() — Returns the hash value of an object; related to
__eq__since defining__eq__makes objects unhashable by default - dunder-str — Defines string representation; another common dunder method for customizing object behavior
- id() — Returns the identity of an object; what equality falls back to when
__eq__is not defined