본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 연산자 오버로딩 시 __radd__ 등 10가지 역방향 메서드의 역할과 해결 방법

by Papa Martino V 2026. 2. 24.
728x90

연산자 오버로딩
연산자 오버로딩

 

파이썬의 객체지향 설계에서 연산자 오버로딩(Operator Overloading)은 사용자 정의 객체가 내장 타입(int, float, list 등)처럼 자연스럽게 동작하게 만드는 핵심 기술입니다. 하지만 많은 개발자가 __add__와 같은 정방향 메서드 구현에만 집중한 나머지, 피연산자의 위치가 바뀔 때 발생하는 TypeError를 해결하지 못해 곤혹을 치르곤 합니다. 이때 구원투수로 등장하는 것이 바로 역방향(Reverse/Reflected) 메서드__radd__, __rsub__ 등입니다. 본 포스팅에서는 파이썬 인터프리터가 연산을 처리하는 우선순위 메커니즘을 분석하고, 외부 라이브러리 객체와의 상호운용성을 극대화하는 전문적인 구현 해결 방안을 심도 있게 다룹니다.


1. 왜 역방향(Reverse) 메서드가 필요한가?

파이썬에서 x + y 연산을 수행할 때, 인터프리터는 먼저 x.__add__(y)를 시도합니다. 만약 x가 우리가 만든 커스텀 객체이고 y가 정수(int)라면 문제가 없지만, 10 + x와 같이 정수가 앞에 오면 상황이 달라집니다. 내장 정수 타입은 우리의 커스텀 객체와 더하는 방법을 알지 못하므로 NotImplemented를 반환하며, 이때 파이썬은 두 번째 피연산자인 x__radd__ 메서드를 찾아 호출합니다. 이것이 바로 상호운용성(Interoperability)의 핵심입니다.


2. 정방향과 역방향 메서드의 실행 우선순위 및 차이 비교

연산 방향에 따른 인터프리터의 의사결정 과정을 아래 표로 명확하게 비교하였습니다.

단계 호출 메서드 실행 조건 해결 차이점 및 비고
1단계 left.__add__(right) 왼쪽 객체에 메서드가 존재할 때 정방향 연산 시도
2단계 right.__radd__(left) 1단계 결과가 NotImplemented일 때 역방향 메서드로 해결
3단계 TypeError 발생 양쪽 모두 처리 불가능할 때 최종 실패 처리

3. __radd__ 구현의 핵심: NotImplemented 반환의 가치

역방향 메서드를 구현할 때 가장 큰 실수는 에러를 직접 발생시키는 것입니다. 전문가의 코드는 자신이 처리할 수 없는 타입이 들어왔을 때 NotImplemented를 반환하여 파이썬 인터프리터가 다른 대안을 찾도록 기회를 넘겨줍니다. 이는 덕 타이핑(Duck Typing) 정신을 유지하는 가장 우아한 방법입니다.


4. Sample Example: 벡터(Vector) 클래스를 통한 실전 구현

숫자와 더할 수 있는 간단한 벡터 객체를 통해 __add____radd__의 상호작용을 살펴보겠습니다.

전문 지식 기반의 코드 설계

class RealVector:
    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        # 정방향: Vector + int
        if isinstance(other, (int, float)):
            return RealVector(self.value + other)
        return NotImplemented

    def __radd__(self, other):
        # 역방향: int + Vector
        # 덧셈은 교환법칙이 성립하므로 __add__로 위임 가능
        return self.__add__(other)

    def __repr__(self):
        return f"Vector({self.value})"

# 실행 결과
v = RealVector(5)
print(v + 10)  # 출력: Vector(15) -> __add__ 호출
print(10 + v)  # 출력: Vector(15) -> __radd__를 거쳐 해결

5. 교환법칙이 성립하지 않는 경우의 해결(예: __rsub__)

덧셈이나 곱셈과 달리 뺄셈(__rsub__)이나 나눗셈은 피연산자의 순서가 중요합니다. 10 - vv - 10과 결과가 다르기 때문입니다. 따라서 역방향 메서드 내부에서 연산의 순서를 정확히 제어하는 것이 논리적 오류를 해결하는 포인트입니다.

Sample Example: 뺄셈 제어

    def __rsub__(self, other):
        # other - self 의 순서로 처리해야 함
        if isinstance(other, (int, float)):
            return RealVector(other - self.value)
        return NotImplemented

6. 결론: 유연한 라이브러리 설계를 위한 제언

파이썬의 역방향 메서드는 단순한 보조 도구가 아니라, 다양한 타입이 혼재된 환경에서도 견고하게 작동하는 다형성(Polymorphism)의 정수입니다. 1. 모든 산술 연산자 오버로딩 시 반드시 쌍을 이루는 Reverse 메서드를 함께 고려하십시오. 2. isinstance 검사를 철저히 하여 예상치 못한 타입과의 연산 시 NotImplemented를 반환하십시오. 3. 교환법칙 성립 여부에 따라 정방향 메서드로의 위임 여부를 결정하십시오.

이러한 세심한 설계는 당신의 코드를 사용하는 다른 개발자들에게 내장 타입과 다를 바 없는 매끄러운 경험을 선사할 것입니다.


7. 내용 출처 및 참고 문헌

  • Python Software Foundation. "Data Model - Emulating numeric types." 파이썬 공식 레퍼런스 가이드.
  • Luciano Ramalho. "Fluent Python: Clear, Concise, and Effective Programming." O'Reilly Media. (연산자 오버로딩 장)
  • Brett Slatkin. "Effective Python." Pearson Education.
  • Alex Martelli. "Python in a Nutshell." O'Reilly Media.
728x90