Python : reflected dunder method 실행조건

파이썬을 사용하여 Operator Overloading 을 시도하려면, dunder(Double Underscore) method 를 사용하면 된다.

def __add__ 등으로 가능한데, 교환법칙(Commutative)이 되는 덧셈/곱셈등은 관계없는 경우도 있지만, 그렇지 않은 뺄셈/나눗셈등을 할 때는, 연산 위치를 신경써줘야 한다.

예를 들어, Class Object 오른쪽에 연산이 가능하게 설계했을 경우, obj1 * 10 은 정상작동하지만, 10 * obj1 은 오류가 나게 된다.

Python 은, 왼쪽항을 기준 클래스로 생각하고, 오른쪽 항을
이를 위해 Reflected method 를 설계해줘야 하는데, 어떤 상황에서 이 메소드가 실행되는지(Triggerd) 그 조건에 대해 정리해본다.


이에 대해, Python 공식 문서에는 이렇게 설명되어 있다.

  1. if the left operand does not support the corresponding operation,
  2. 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 가 발생하게 된다.


설명이 됐으려나??

Author: 아무도안

안녕하세요. 글 남겨주셔서 고맙습니다.