수색…


매직 / 썬더 방법

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 매개 변수 ( modulopow 내장 함수에서만 사용됩니다.


이항 연산자에 해당하는 각 메서드에는 __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__ 과 같은 특수 메서드가 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow