본문 바로가기
Computer Science/[20-3,4] Python Basic

[Python] Operator Overloading (3) 클래스 객체 간의 연산과 역순 연산자

by gojw 2020. 4. 2.

<목차>

① (예시) + 연산자에 대한 설명

② 역순 연산자의 이해

③ 순서가 있는 연산자의 역순 연산자를 쓸때

 

class Number:

    def __init__(self, number):
        self.number = number


n1 = Number(1)
n2 = Number(1)

print(n1 + n2)
# TypeError: unsupported operand type(s) for +: 'Number' and 'Number'
print(n1 + 100)
# TypeError: unsupported operand type(s) for +: 'Number' and 'int'

여기 아주 간단한 클래스 Number가 있다. 생성자 메소드만을 포함하고 있다.

파이썬에서 본인이 만든 클래스의 객체끼리 연산자를 사용할 수 없다.

또 클래스의 객체와 다른 빌트인 객체 간이 연산도 되지 않는다.

 

① (예시) + 연산자에 대한 설명

o1 + o2

파이썬에서 이러한 더하기 연산을 하려고 하면,

type(o1).__add__(o1, o2)

의 형식으로 바꿔주어야 한다.

 

아래의 예시를 보면,

class Number:

    def __init__(self, number):
        self.number = number


n1 = Number(1)
n2 = Number(1)

print(type(n1))
# <class '__main__.Number'>
print(type(10))
# <class 'int'>
print(n1 + 10)
# TypeError: unsupported operand type(s) for +: 'Number' and 'int'

 type() 함수는 객체의 데이터 타입을 확인할 수 있는 함수이다. 이 함수를 통해서,

n1은 __main__.Number의 인스턴스이고, 10은 int 클래스의 인스턴스임을 확인할 수 있다.

이제 더하기 연산을 실행한다고 생각해보자,

n1 + 10

type(n1).__add__(n1, 10) 으로 실행이 되는데,

n1의 클래스인 Number에는 __add__()라는 Dunder Method가 존재하지 않는다.

 

따라서 이 연산을 수행하기 위해, Number 클래스에 __add__()를 추가해보자.

class Number:

    def __init__(self, number):
        self.number = number

    def __add__(self, other):
        return self.number + other

n1 = Number(1)
n2 = Number(1)

print(n1 + 10)
# 11

→ 원하는 대로 실행이 되었다! 하지만 여기서 문제는 반대의 경우,

10 + n1 이 작동하지 않는다.

이 연산은 type(10).__add__(10, n1) 으로 실행이 되는데,

이렇게 인스턴스 객체가 오른쪽으로 이동하면 __radd__() 가 호출이 된다.

하지만 우리가 만든 클래스 안에 __radd__()가 존재하지 않으니, 추가해주면 된다.

class Number:

    def __init__(self, number):
        self.number = number

    def __add__(self, other):
        return self.number + other

    def __radd__(self, other):
        return self.number + other

n1 = Number(1)
n2 = Number(1)

print(10 + n1)

 

② 역순 연산자의 이해

위에서 사용한 __radd__()의 이름은 역순 연산자이다.

기존 연산자의 Dunder Method 앞에 'r'을 붙여주면 역순 연산자가 된다.

 

이 연산자는 right operand로, 인스턴스 객체가 오른쪽에 있을 때 쓰인다.

__radd__()는 파이썬이 left operand __add__() 호출을 실패하면 시도하고, 인자의 순서를 바꿔서 연산한다.

 

③ 순서가 있는 연산자의 역순 연산자를 쓸때

//, **, %, - 등 순서가 중요한 연산자를 사용할 때에는 역순 연산자의 리턴값에 주의한다.

# correct
class Number:

    def __init__(self, number):
        self.number = number

    def __sub__(self, other):
        return self.number - other

    def __rsub__(self, other):
        return other - self.number

n1 = Number(1)
n2 = Number(1)

print(n1 - 100)
# -99
print(100 - n1)
# 99

# wrong
class Number:

    def __init__(self, number):
        self.number = number

    def __sub__(self, other):
        return self.number - other

    def __rsub__(self, other):
        return self.number - other

n1 = Number(1)
n2 = Number(1)

print(n1 - 100)
# -99
print(100 - n1)
# -99	# Wrong!

댓글