Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬에서 __lt__, __gt__ 매직 메서드로 비교 연산자 오버로딩 구현하기

파이썬 매직 메서드로 비교 연산자 오버로딩하기

파이썬에는 연산자의 기본 동작을 재정의(오버로딩)할 수 있도록 매직 메서드(magic method)라고 불리는 특수 메서드가 마련되어 있습니다. 비교 연산자인 <, <=, >, >=, ==, != 는 각각 __lt__, __le__, __gt__, __ge__, __eq__, __ne__ 매직 메서드를 클래스 내에 정의하는 방식으로 오버로딩할 수 있습니다.

아래 예제는 거리(Distance) 클래스의 객체끼리 서로 비교할 수 있도록 < 연산자와 > 연산자를 오버로딩한 프로그램입니다. 두 객체를 비교할 때는 피트(ft)와 인치(inch)를 모두 인치 단위로 환산한 전체 길이를 기준으로 크기를 판단합니다.

class Distance:
    def __init__(self, ft=5, inch=5):
        self.ft = ft       # 피트
        self.inch = inch   # 인치

    def __eq__(self, other):          # == 연산자 오버로딩
        if self.ft == other.ft and self.inch == other.inch:
            return "두 객체는 서로 같습니다"
        return "두 객체는 서로 같지 않습니다"

    def __lt__(self, other):          # < 연산자 오버로딩
        in1 = self.ft * 12 + self.inch    # 전체 길이를 인치로 환산
        in2 = other.ft * 12 + other.inch
        if in1 < in2:
            return "첫 번째 객체가 더 작습니다"
        return "첫 번째 객체가 더 작지 않습니다"

    def __gt__(self, other):          # > 연산자 오버로딩
        in1 = self.ft * 12 + self.inch
        in2 = other.ft * 12 + other.inch
        if in1 > in2:
            return "첫 번째 객체가 더 큽니다"
        return "첫 번째 객체가 더 크지 않습니다"


d1 = Distance(5, 5)
d2 = Distance()
print(d1 == d2)   # 두 객체가 같은지 비교
print(d1 > d2)    # 크기 비교

d3 = Distance()
d4 = Distance(6, 10)
print(d3 < d4)    # 작음 여부 비교

d5 = Distance(3, 11)
d6 = Distance()
print(d5 < d6)

실행 결과

아래 결과를 통해 __lt____gt__ 매직 메서드가 실제로 어떻게 동작하는지 확인할 수 있습니다.

두 객체는 서로 같습니다
첫 번째 객체가 더 크지 않습니다
첫 번째 객체가 더 작습니다
첫 번째 객체가 더 작습니다

코드 설명

__lt__ 메서드는 < 연산자가, __gt__ 메서드는 > 연산자가 사용되는 순간 파이썬 인터프리터에 의해 자동으로 호출됩니다. 예를 들어 d5 < d6이라는 표현식은 내부적으로 d5.__lt__(d6) 형태로 변환되어 실행됩니다.

비교 로직을 살펴보면, 먼저 self.ft * 12 + self.inch 계산을 통해 피트와 인치를 하나의 인치 값으로 통합합니다. 이렇게 단위를 통일해야 서로 다른 조합(예: 3피트 11인치와 5피트 0인치)의 객체도 정확하게 비교할 수 있습니다.

참고로 실무에서는 비교 메서드가 위 예제처럼 문자열이 아니라 True 또는 False 불리언 값을 반환하도록 구현하는 것이 일반적입니다. 불리언을 반환해야 sorted(), max() 같은 내장 함수와 함께 자연스럽게 활용할 수 있기 때문입니다. 또한 functools.total_ordering 데코레이터를 사용하면 __eq__와 비교 메서드 하나만 정의해도 나머지 비교 연산자들이 자동으로 완성되므로, 여러 비교 연산자를 구현할 때 유용하게 활용할 수 있습니다.