Python Language
오버로딩
수색…
매직 / 썬더 방법
Python의 Magic (double-underscore의 약어로 dunder라고도 함) 메소드는 다른 언어로 연산자 오버로딩과 비슷한 목적을 수행합니다. 이 클래스를 사용하면 클래스가 단항 또는 2 진 연산자 표현식에서 피연산자로 사용될 때 클래스의 동작을 정의 할 수 있습니다. 그것들은 또한 몇몇 내장 함수에 의해 호출되는 구현체로서 기능한다.
이 2 차원 벡터의 구현을 고려하십시오.
import math
class Vector(object):
# instantiation
def __init__(self, x, y):
self.x = x
self.y = y
# unary negation (-v)
def __neg__(self):
return Vector(-self.x, -self.y)
# addition (v + u)
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
# subtraction (v - u)
def __sub__(self, other):
return self + (-other)
# equality (v == u)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
# abs(v)
def __abs__(self):
return math.hypot(self.x, self.y)
# str(v)
def __str__(self):
return '<{0.x}, {0.y}>'.format(self)
# repr(v)
def __repr__(self):
return 'Vector({0.x}, {0.y})'.format(self)
이제 다양한 표현식에서 Vector
클래스의 인스턴스를 자연스럽게 사용할 수 있습니다.
v = Vector(1, 4)
u = Vector(2, 0)
u + v # Vector(3, 4)
print(u + v) # "<3, 4>" (implicit string conversion)
u - v # Vector(1, -4)
u == v # False
u + v == v + u # True
abs(u + v) # 5.0
컨테이너 및 시퀀스 유형
키 또는 인덱스별로 값에 액세스하는 것을 지원하는 컨테이너 유형을에 D 레이트 할 수 있습니다.
메모리를 절약하기 위해 0이 아닌 요소 만 저장하는 스파 스 목록의 순진 구현을 고려하십시오.
class sparselist(object):
def __init__(self, size):
self.size = size
self.data = {}
# l[index]
def __getitem__(self, index):
if index < 0:
index += self.size
if index >= self.size:
raise IndexError(index)
try:
return self.data[index]
except KeyError:
return 0.0
# l[index] = value
def __setitem__(self, index, value):
self.data[index] = value
# del l[index]
def __delitem__(self, index):
if index in self.data:
del self.data[index]
# value in l
def __contains__(self, value):
return value == 0.0 or value in self.data.values()
# len(l)
def __len__(self):
return self.size
# for value in l: ...
def __iter__(self):
return (self[i] for i in range(self.size)) # use xrange for python2
그런 다음 일반 list
과 매우 유사한 sparselist
사용할 수 있습니다.
l = sparselist(10 ** 6) # list with 1 million elements
0 in l # True
10 in l # False
l[12345] = 10
10 in l # True
l[12345] # 10
for v in l:
pass # 0, 0, 0, ... 10, 0, 0 ... 0
호출 가능 유형
class adder(object):
def __init__(self, first):
self.first = first
# a(...)
def __call__(self, second):
return self.first + second
add2 = adder(2)
add2(1) # 3
add2(2) # 4
구현되지 않은 동작 처리
클래스가 제공하는 인수 유형에 대한 특정 오버로드 된 연산자를 구현하지 않는 경우, 그것은해야 return NotImplemented
(이것은이므로주의 특별한 일정 이 아닌 같은 NotImplementedError
). 이렇게하면 파이썬은 다른 방법을 시도하여 작업을 수행 할 수 있습니다.
NotImplemented
가 반환되면 인터프리터는 연산자에 따라 다른 형식 또는 다른 대체 형식에서 반사 된 연산을 시도합니다. 시도한 모든 작업이NotImplemented
반환하면 인터프리터는 적절한 예외를 발생시킵니다.
예를 들어, x + y
주어지면 x.__add__(y)
가 구현되지 않은 것을 반환하면 y.__radd__(x)
가 대신 시도됩니다.
class NotAddable(object):
def __init__(self, value):
self.value = value
def __add__(self, other):
return NotImplemented
class Addable(NotAddable):
def __add__(self, other):
return Addable(self.value + other.value)
__radd__ = __add__
이것이 반영된 방법 __radd__
모든 경우에 예상되는 동작을 얻으려면 __add__
및 __radd__
을 구현해야합니다. 다행히도,이 간단한 예제에서 둘 다 똑같은 것을하고 있기 때문에, 우리는 지름길을 취할 수 있습니다.
사용:
>>> x = NotAddable(1)
>>> y = Addable(2)
>>> x + x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'NotAddable' and 'NotAddable'
>>> y + y
<so.Addable object at 0x1095974d0>
>>> z = x + y
>>> z
<so.Addable object at 0x109597510>
>>> z.value
3
연산자 오버로딩
다음은 클래스에서 오버로드 될 수있는 연산자와 필요한 메서드 정의 및 표현식에서 사용중인 연산자의 예입니다.
주의 변수 이름으로 other
를 사용하는 것은 필수는 아니지만 표준으로 간주됩니다.
운영자 | 방법 | 표현 |
---|---|---|
+ 추가 | __add__(self, other) | a1 + a2 |
- 뺄셈 | __sub__(self, other) | a1 - a2 |
* 곱셈 | __mul__(self, other) | a1 * a2 |
@ 매트릭스 곱셈 | __matmul__(self, other) | a1 @ a2 ( 파이썬 3.5 ) |
/ 부문 | __div__(self, other) | a1 / a2 ( 파이썬 2 전용 ) |
/ 부문 | __truediv__(self, other) | a1 / a2 ( 파이썬 3 ) |
// 층 구분 | __floordiv__(self, other) | a1 // a2 |
모듈러스 / 나머지 % | __mod__(self, other) | a1 % a2 |
** 힘 | __pow__(self, other[, modulo]) | a1 ** a2 |
<< 비트 왼쪽 시프트 | __lshift__(self, other) | a1 << a2 |
>> 비트 오른쪽 시프트 | __rshift__(self, other) | a1 >> a2 |
& 비트 AND | __and__(self, other) | a1 & a2 |
^ 비트 XOR | __xor__(self, other) | a1 ^ a2 |
| (비트 OR) | __or__(self, other) | a1 | a2 |
- 부정 (산술) | __neg__(self) | -a1 |
+ 긍정적 | __pos__(self) | +a1 |
~ 비트 NOT | __invert__(self) | ~a1 |
< 보다 작음 | __lt__(self, other) | a1 < a2 |
<= 보다 작거나 같음 | __le__(self, other) | a1 <= a2 |
== 같음 | __eq__(self, other) | a1 == a2 |
!= 같지 않음 | __ne__(self, other) | a1 != a2 |
> 보다 큼 | __gt__(self, other) | a1 > a2 |
>= 크거나 같음 | __ge__(self, other) | a1 >= a2 |
[index] 인덱스 연산자 | __getitem__(self, index) | a1[index] |
in 연산자 | __contains__(self, other) | a2 in a1 |
(*args, ...) 호출 | __call__(self, *args, **kwargs) | a1(*args, **kwargs) |
__pow__
에 대한 modulo
매개 변수 ( modulo
는 pow
내장 함수에서만 사용됩니다.
이항 연산자에 해당하는 각 메서드에는 __r
시작하는 해당 "올바른"메서드가 있습니다 (예 : __radd__
.
class A:
def __init__(self, a):
self.a = a
def __add__(self, other):
return self.a + other
def __radd__(self, other):
print("radd")
return other + self.a
A(1) + 2 # Out: 3
2 + A(1) # prints radd. Out: 3
해당 inplace 버전은 __i
시작합니다.
class B:
def __init__(self, b):
self.b = b
def __iadd__(self, other):
self.b += other
print("iadd")
return self
b = B(2)
b.b # Out: 2
b += 1 # prints iadd
b.b # Out: 3
이 메소드에는 특별한 것이 없으므로 언어의 많은 부분, 표준 라이브러리의 부분 및 심지어 타사 모듈까지도 객체를 유형에 캐스팅하거나 객체의 속성을 확인하는 메소드와 같이 자체적으로 마법 메서드를 추가합니다. 예를 들어, 내장 된 str()
함수는 객체의 __str__
메소드가 있으면 호출합니다. 이러한 용도 중 일부는 다음과 같습니다.
기능 | 방법 | 표현 |
---|---|---|
int | __int__(self) | int(a1) |
절대 함수 | __abs__(self) | abs(a1) |
str 캐스트 | __str__(self) | str(a1) |
unicode | __unicode__(self) | unicode(a1) (파이썬 2 전용) |
문자열 표현 | __repr__(self) | repr(a1) |
부 bool | __nonzero__(self) | bool(a1) |
문자열 서식 지정 | __format__(self, formatstr) | "Hi {:abc}".format(a1) |
해싱 | __hash__(self) | hash(a1) |
길이 | __len__(self) | len(a1) |
반전 된 | __reversed__(self) | reversed(a1) |
바닥 | __floor__(self) | math.floor(a1) |
천장 | __ceil__(self) | math.ceil(a1) |
또한 컨텍스트 관리자를위한 __enter__
및 __exit__
과 같은 특수 메서드가 있습니다.