13.1. 연산자 오버로딩 기본 지식
- 파이썬은 다음과 같은 제한을 두어 융통성, 사용성, 안전성을 적절히 유지한다.
1. 내장 자료형에 대한 연산자는 오버로딩할 수 없다.
2. 새로운 연산자를 생성할 수 없으며, 기존 연산자를 오버로딩만 할 수 있다.
3. is, and, or, not 연산자는 오버로딩할 수 없다(그러나 &, |, ~ 비트 연산자는 가능하다).
13.2. 단항 연산자
- (__neg__): 단항 산술 부정. x가 -2이면 -x는 2이다.
+ (__pos__): 단항 산술 덧셈. 일반적으로 x와 +x는 동일하지만, 그렇지 않은 경우도 있다.
~ (__invert__): 정수형의 비트 반전. ~x는 -(x+1)로 정의된다(~x == -(x+1)). x가 2면, ~x는 -3이다.
- 단항 연산자는 self 인수 하나를 받는 적절한 특별 메서드를 구현함으로써 구현할 수 있다.
13.3. 벡터를 더하기 위해 + 오버로딩하기
- 길이가 다른 두 개의 Vector 객체를 더했을 때 짧은 쪽 벡터의 빈 공간을 0으로 채우는 __add__() 메서드 구현하기
# Vector 클래스 내부
def __add__(self, other):
paris = itertools.zip_longest(self, other, fillvalue=0.0) # 길이가 다를 경우 짧은 쪽 반복형의 빠진 값을 fillvalue로 채운다.
return Vector(a + b for a, b in pairs) # 새로운 Vector 객체 생성
- __radd__() 메서드는 __add__() 메서드의 역순 버전이다.
# Vector 클래스 내부
def __add__(self, other):
paris = itertools.zip_longest(self, other, fillvalue=0.0) # 길이가 다를 경우 짧은 쪽 반복형의 빠진 값을 fillvalue로 채운다.
return Vector(a + b for a, b in pairs) # 새로운 Vector 객체 생성
def __radd__(self, other): # __radd__()는 단지 __add__() 메서드에 처리를 위임한다.
return self + other
- ohter 피연산자의 자료형이나 그 안에 들어 있는 요소의 자료형을 검사하지 않고, 대신 예외를 잡은 후 NotImplemented를 반환함으로써 벡터 덧셈을 수행하는 특별 메서드를 다음과 같이 구현할 수 있다.
def __add__(self, other):
try:
pairs = itertools.zip_longest(self, other, fillvalue=0.0)
return Vector(a + b for a, b in pairs)
except TypeError:
return NotImplemented
def __radd__(self, other):
return self + other
13.4. 벡터를 스칼라와 곱하기 위해 * 오버로딩하기
def __mul__(self, scalar):
if isinstance(scalar, numbers.Real): # 자료형 검사.
return Vector(n * scalar for n in self)
else:
return NotImplemented
def __rmul__(self, scalar):
return self * scalar
13.5. 향상된 비교 연산자
- 개선된 __eq__() 메서드
def __eq__(self, other):
if isinstance(other, Vector):
return (len(self) == len(other) and
all(a == b for a, b in zip(self, other)))
else:
return NotImplemented
13.6. 복합 할당 연산자
+와 +=를 지원하기 위해 BingoCage를 확장한 클래스
import itertools
class AddableBingoCage(BingoCage):
def __add__(self, other):
if isinstance(other, Tombola):
return AddableBingoCage(self.inspect() + other.inspect()) # other 객체에서 항목을 가져온다.
else:
return NotImplemented
def __iadd__(self, other):
if isinstance(other, Tombola):
other_iterable = other.inspect()
else:
try:
other_iterable = iter(other) # Tombola 객체가 아닐 때는 other의 반복자를 가져온다.
except TypeError:
self_cls = type(self).__name__
msg = "right operand in += must be {!r} or an iterable"
raise TypeError(msg.format(self_cls))
self.load(other_iterable) # other_iterable을 self에 로딩한다.
return self # 할당 연산 특별 메서드는 반드시 self를 반환해야 한다.
__add__(): AddableBingoCage()를 호출해서 생성된 새로운 객체를 반환한다.
__iadd__(): 객체 자신을 변경한 후 self를 반환한다.
'Python' 카테고리의 다른 글
[전문가를 위한 파이썬] 12장 내장 자료형 상속과 다중 상속 (1) | 2024.08.31 |
---|---|
[전문가를 위한 파이썬] 11장 인터페이스: 프로토콜에서 ABC까지 (0) | 2024.08.31 |
[전문가를 위한 파이썬] 10장 시퀀스 해킹, 해시, 슬라이스 (0) | 2024.07.21 |
[전문가를 위한 파이썬] 9장 파이썬스러운 객체 내용 정리 (0) | 2024.06.22 |
[전문가를 위한 파이썬] 8장 객체 참조, 가변성, 재활용 내용 정리 (0) | 2024.06.18 |