파이썬 클래스 객체를 == 연산자로 비교하면 왜 False가 나올까?
사용자 정의 클래스의 인스턴스 두 개를 만들고 아래 코드처럼 등가(equality) 연산자 ==로 비교하면, 겉보기에는 같은 값을 가졌음에도 불구하고 결과는 False로 출력됩니다.
class Integer:
def __init__(self, number):
self.number = number
n1 = Integer(1)
n2 = Integer(1)
print bool(n1 == n2)
출력 결과:
False
원인: 기본 비교는 '객체 식별자' 기준
파이썬은 별도의 설정이 없을 경우 비교 연산 시 객체 자체의 값이 아니라 객체 식별자(identity), 즉 메모리상의 참조 위치를 기준으로 판단합니다. n1과 n2는 서로 다른 인스턴스이므로 식별자가 다르고, 그 결과 False가 반환되는 것입니다.
해결 방법: __eq__ 메서드 오버라이딩
이 문제를 해결하려면 클래스 내에서 __eq__ 메서드를 직접 오버라이딩하여 값 기반의 비교 로직을 정의해야 합니다.
class Integer:
def __init__(self, number):
self.number = number
def __eq__(self, other):
if isinstance(self, other.__class__):
return self.__dict__ == other.__dict__
return False
n1 = Integer(1)
n2 = Integer(1)
print bool(n1 == n2)
print bool(n1 != n2)
출력 결과:
True
True
위 예제에서는 두 객체의 내부 속성 딕셔너리(__dict__)를 비교하여 값이 같으면 True를 반환하도록 구현했습니다.
Python 2.x와 3.x의 차이점: __ne__ 처리
Python 2.x에서는 !=(부등가) 연산이 올바르게 동작하도록 하려면 __ne__ 메서드도 함께 오버라이딩해야 합니다. 반면 Python 3.x에서는 이 작업이 필요하지 않습니다.
공식 문서에 따르면 다음 사항이 성립합니다:
기본적으로
__ne__()는__eq__()에 위임(delegate)하여 그 결과를 반전시킵니다. 단, 결과가NotImplemented인 경우는 제외됩니다. 비교 연산자들 사이에는 이 외에 어떠한 암묵적인 관계도 존재하지 않습니다. 예를 들어,(x < y or x == y)가 참이라고 해서x <= y가 참이 되는 것은 아닙니다.
정리하면, 파이썬 3 이상 환경에서는 __eq__만 정의해도 ==와 != 모두 일관되게 동작하지만, 파이썬 2 환경을 지원해야 한다면 __ne__까지 명시적으로 구현하는 것이 안전합니다.