파이썬을 사용하여 Operator Overloading 을 시도하려면, dunder(Double Underscore) method 를 사용하면 된다.
def __add__
등으로 가능한데, 교환법칙(Commutative)이 되는 덧셈/곱셈등은 관계없는 경우도 있지만, 그렇지 않은 뺄셈/나눗셈등을 할 때는, 연산 위치를 신경써줘야 한다.
예를 들어, Class Object 오른쪽에 연산이 가능하게 설계했을 경우, obj1 * 10
은 정상작동하지만, 10 * obj1
은 오류가 나게 된다.
Python 은, 왼쪽항을 기준 클래스로 생각하고, 오른쪽 항을
이를 위해 Reflected method 를 설계해줘야 하는데, 어떤 상황에서 이 메소드가 실행되는지(Triggerd) 그 조건에 대해 정리해본다.
이에 대해, Python 공식 문서에는 이렇게 설명되어 있다.
- if the left operand does not support the corresponding operation,
- the operands are of different types
첫번째, 왼쪽에 있는 피연산자(Operand)가 해당연산을 지원하지 않고
두번째, 양쪽 피연산자가 서로 다른 형식일 때,
오른쪽 항목에 있는 클래스의 Reflected Method 가 실행된다고 한다. (물론, 오른항에 r.method 가 구현되어 있어야 한다.)
예를 들어보자면 이렇다.
foo 라는 클래스가 있고, 이것으로 bar 라는 객체를 만들었다.
foo * int 는 __mul__
로 구현을 했다. 따라서, bar * 12
등은 잘 작동한다.
그러나, 12 * bar
는 아직 만들지 않았다. 이 상태에서 이대로 실행한다면, 다음과 같은 오류가 발생한다.
3 * bar --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-8-3500758b515f> in <module> ----> 1 3 * bar TypeError: unsupported operand type(s) for *: 'int' and 'foo'
이걸 위의 설명에 미루어보면, 3 * bar 에서, 먼저, 3.__mul__(bar)
가 진행된다. 그런데, 3, 즉 int 클래스 입장에선 bar 를 알지 못하므로, NotImplemented 가 발생한다. 이게 위에서 설명한 첫번째 조건(if the left operand does not support the corresponding operation)이 된다.
이럴 경우, 오른쪽 항(bar)의 클래스(foo)에 __rmul__ 이 구현돼 있다면, bar.__rmul__(3) 이 실행된다. rmul 이 없다면, 그제서야 비로소 TypeError 가 발생하게 된다.
설명이 됐으려나??