__eq__(==)와 __ne__(!=) 매직메서드는 두 객체가 같은지 또는 다른지를 비교합니다.
class Book:
def __init__(self, title, isbn):
self.title = title
self.isbn = isbn
def __eq__(self, other):
if not isinstance(other, Book):
return NotImplemented
return self.isbn == other.isbn
def __ne__(self, other):
if not isinstance(other, Book):
return NotImplemented
return self.isbn != other.isbn
def __str__(self):
return f"Book({self.title})"
# 같은 ISBN을 가진 두 책
book1 = Book("Python Basic", "123-456")
book2 = Book("파이썬 기초", "123-456")
print(f"같은 책?: {book1 == book2}") # True (ISBN이 같음)
# 다른 ISBN을 가진 책
book3 = Book("Python Basic", "789-123")
print(f"다른 책?: {book1 != book3}") # True (ISBN이 다름)
위 코드에는 동등성 비교를 할 때 주의할 만한 것을 담아두었습니다.
isinstance() 체크로 타입 안전성 확보
NotImplemented 반환으로 다른 타입과의 비교 허용
__ne__는 __eq__의 반대로 구현
이렇게 하지 않으면 아래와 같은 오해가 생길 수 있습니다. book1이 비어있지 않은데 비어있는 것처럼 반환되는 것이죠. 따라서 타입확인과 NotImplemented 반환을 통해 이러한 오해를 방지할 수 있습니다.
class Book:
def __eq__(self, other):
return True
book = Book()
print(book == "Python") # True가 되어버림 (의도하지 않은 동작)
print(book == None) # AttributeError 발생!
class Book:
def __init__(self, title):
self.title = title
def __eq__(self, other):
if not isinstance(other, Book): # 타입 체크
return NotImplemented
return self.title == other.title
book = Book("Python")
print(book == "Python") # False (의도한 대로 동작)
print(book == None) # False (안전하게 동작)
2. 순서 비교 (Ordering)
__lt__(<), __le__(<=), __gt__(>), __ge__(>=) 매직메서드로 객체 간의 순서를 정의할 수 있습니다. 여기서 순서라고 얘기한 것은 단지 크기비교로도 해당 매직메서드가 사용되지만 max, min 등의 함수를 사용할 때에도 해당 매직메서드가 사용된다는 것을 의미합니다.