매직 메서드 - 비교 연산
1. 동등성 비교 (Equality)
__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
book1 = Book()
book1 == None
2. 순서 비교 (Ordering)
__lt__
(<), __le__
(<=), __gt__
(>), __ge__
(>=) 매직메서드로 객체 간의 순서를 정의할 수 있습니다.
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
def __lt__(self, other):
if not isinstance(other, Temperature):
return NotImplemented
return self.celsius < other.celsius
def __le__(self, other):
if not isinstance(other, Temperature):
return NotImplemented
return self.celsius <= other.celsius
def __str__(self):
return f"{self.celsius}°C"
# 온도 비교
temp1 = Temperature(20)
temp2 = Temperature(25)
print(f"{temp1} < {temp2}: {temp1 < temp2}") # True
print(f"{temp1} <= {temp2}: {temp1 <= temp2}") # True
3. total_ordering 데코레이터 활용
@total_ordering
데코레이터를 사용하면 __lt__
와 __eq__
만 구현해도 나머지 비교 연산자가 자동으로 구현됩니다.
from functools import total_ordering
@total_ordering
class Grade:
def __init__(self, score):
self.score = score
def __eq__(self, other):
if not isinstance(other, Grade):
return NotImplemented
return self.score == other.score
def __lt__(self, other):
if not isinstance(other, Grade):
return NotImplemented
return self.score < other.score
def __str__(self):
return f"Grade({self.score})"
# 성적 비교
math = Grade(85)
science = Grade(90)
history = Grade(85)
print(f"{math} < {science}: {math < science}") # True
print(f"{math} == {history}: {math == history}") # True
print(f"{math} > {science}: {math > science}") # False (자동 구현)
print(f"{math} >= {history}: {math >= history}") # True (자동 구현)
4. 실제 활용 예시
실제 프로그래밍에서 자주 사용되는 버전 비교 예제입니다.
class Version:
def __init__(self, major, minor, patch):
self.major = major
self.minor = minor
self.patch = patch
def __eq__(self, other):
if not isinstance(other, Version):
return NotImplemented
return (self.major, self.minor, self.patch) == \
(other.major, other.minor, other.patch)
def __lt__(self, other):
if not isinstance(other, Version):
return NotImplemented
return (self.major, self.minor, self.patch) < \
(other.major, other.minor, other.patch)
def __str__(self):
return f"v{self.major}.{self.minor}.{self.patch}"
# 버전 비교
v1 = Version(2, 0, 0)
v2 = Version(2, 1, 0)
v3 = Version(2, 1, 0)
print(f"{v1} < {v2}: {v1 < v2}") # True
print(f"{v2} == {v3}: {v2 == v3}") # True {"packages":["numpy","pandas","matplotlib","lxml"]}