반응형
20. 연산자 오버로드 (1)
20.2 연산자 오버로드
- 곱셈/덧셈의 특수 메소드를 사용하여 연산자 오버로드를 했다.
# Variable 간 *를 사용하면 1) __mul__ 메소드가 호출, 2) 그 안의 mul() 함수를 호출
def __mul__(self, other):
# a * b 연산시 a는 self, b는 other에 대응
return mul(self, other)
def __add__(self, other):
return add(self, other)
# 파이썬에서는 함수도 객체이므로 함수 자체를 할당하여 처리하면 다음과 같이 작성할 수 있다.
Variable.__mul__ = mul
Variable.__add__ = add
21. 연산자 오버로드 (2)
21.1 ndarray와 함께 사용하기
-
Variable 인스턴스 a,b가 있을 때 'a*b, a+b'와 같은 코드를 작성할 수 있지만 몇가지 제한이 있다.
- a*np.array(2.0)과 같이 ndarray 인스턴스와 함께 사용할 수 없다.
- 3+b와 같이 수치 데이터를 같이 사용할 수 없다.
-
본 장에서는 이를 함께 사용할 수 있게끔 코드를 구현한다.
-
a가 Variable 인스턴스일 때 a * np.array(2.0)이라는 코드를 만나면 ndarray 인스턴스를 자동으로 Variable 인스턴스로 변환
( np.array(2.0) -> Variable(np.array(2.0)) )
-
def as_variable(obj):
"""
인수 obj가 Variable 인스턴스면 그대로 반환
그렇지 않으면 Variable 인스턴스로 변환하여 반환
"""
if isinstance(obj, Variable):
return obj
return Variable(obj)
21.2 float, int와 함께 사용하기
-
작성했던 add()에 "as_array()"를 추가하여 위에서 구현했던 것과 합치는 것은 부분적으로만 해결해주며, 크게 두 가지 문제점이 있다.
1. 첫 번째 인수가 float나 int인 경우
y = 2.0 * x
- '*' 같은 이항 연산자는 피연산자의 위치에 따라 호출되는 특수 메소드가 다르다.
- 곱셈의 경우 피연산자가 좌항이면 mul, 우항이면 rmul이 호출된다.
- 이는 다음 특수 메소드를 추가해주면 된다.
# __add__와 __radd__는 self, other에 대응하는 변수의 순서에 차이가 있다. mul도 같음. Variable.__add__ = add Variable.__radd__ = add Variable.__mul__ = mul Variable.__rmul__ = mul
2. 좌항이 ndarray 인스턴스인 경우
- 좌항이 ndarray 인스턴스이고 우항이 Variable 인스턴스면 좌항인 ndarray의 add 메소드가 호출된다.
- 하지만, Variable 인스턴스인 radd 메소드가 호출되길 원한다.
- 이를 위해서 '연산자 우선순위'를 지정해야한다.
- Variable 인스턴스 속성에 array_priority를 추가하고 그 값을 큰 정수로 설정해야 한다.
- '*' 같은 이항 연산자는 피연산자의 위치에 따라 호출되는 특수 메소드가 다르다.
22. 연산자 오버로드 (3)
- 새로운 연산자를 추가하려면 다음 세 스텝을 밟으면 된다.
- Function 클래스를 상속하여 원하는 함수 클래스를 구현한다. (예: Mul 클래스)
- 파이썬 함수로 사용할 수 있게 만든다. (예: mul 함수)
- Variable 클래스의 연산자를 오버로드한다. (예: Variable.__mul__ = mul)
반응형
'컴퓨터 > 밑딥3' 카테고리의 다른 글
[밑바닥부터 시작하는 딥러닝3] 딥러닝 프레임워크의 동작 방식 (0) | 2020.12.18 |
---|---|
[밑바닥부터 시작하는 딥러닝3] 메모리 관리 (0) | 2020.12.13 |