numbers — 숫자 추상 베이스 클래스¶
소스 코드: Lib/numbers.py
numbers 모듈(PEP 3141)은 숫자에 대한 추상 베이스 클래스 의 계층 구조를 정의합니다. 계층 구조가 깊어질수록 더 많은 연산이 정의되어 있습니다. 이 모듈에 정의된 모든 형은 인스턴스로 만들 수 없습니다.
- class numbers.Number¶
숫자 계층의 최상위 클래스입니다. 형에 상관없이 인자 x 가 숫자인지 확인하려면
isinstance(x, Number)를 사용하세요.
숫자 계층¶
- class numbers.Complex¶
이 서브 클래스는 복소수를 표현하고 내장
complex형에 사용되는 연산을 포함합니다. 여기에는complex와bool형으로의 변환과real,imag,+,-,*,/,**,abs(),conjugate(),==,!=이 포함됩니다.-와!=를 제외하고는 모두 추상입니다.- real¶
추상. 복소수의 실수부를 반환합니다.
- imag¶
추상. 복소수의 허수부를 반환합니다.
- abstractmethod conjugate()¶
추상 메서드. 켤레 복소수를 반환합니다. 예를 들어
(1+3j).conjugate() == (1-3j)입니다.
- class numbers.Real¶
Real클래스는Complex클래스에 실수 연산을 추가합니다.요약하면
float로의 변환과math.trunc(),round(),math.floor(),math.ceil(),divmod(),//,%,<,<=,>,>=가 포함됩니다.이 클래스는 또한
complex(),real,imag,conjugate()를 위한 기본값을 제공합니다.
- class numbers.Rational¶
Real의 하위 형이고numerator와denominator프로퍼티가 추가됩니다. 또한float()함수를 위한 기본값을 제공합니다.The
numeratoranddenominatorvalues should be instances ofIntegraland should be in lowest terms withdenominatorpositive.- numerator¶
Abstract. The numerator of this rational number.
- denominator¶
Abstract. The denominator of this rational number.
형 구현자를 위한 주의 사항¶
Implementers should be careful to make equal numbers equal and hash them to the same values. This may be subtle if there are two different extensions of the real numbers. See also Hashing of numeric types.
Adding more numeric ABCs¶
물론 숫자를 위한 ABC를 추가하는 것이 가능합니다. 그렇지 않으면 엉망으로 상속 계층이 구현될 것입니다. Complex 와 Real 사이에 다음과 같이 MyFoo 를 추가할 수 있습니다:
class MyFoo(Complex): ...
MyFoo.register(Real)
산술 연산 구현¶
다른 형에 대한 연산은 두 인자의 형에 관해 알고 있는 구현을 호출하거나 두 인자를 가장 비슷한 내장형으로 변환하여 연산하도록 산술 연산을 구현하는 것이 좋습니다. Integral 클래스의 하위 형일 경우에 __add__() 와 __radd__() 메서드는 다음과 같이 정의되어야 함을 의미합니다:
class MyIntegral(Integral):
def __add__(self, other):
if isinstance(other, MyIntegral):
return do_my_adding_stuff(self, other)
elif isinstance(other, OtherTypeIKnowAbout):
return do_my_other_adding_stuff(self, other)
else:
return NotImplemented
def __radd__(self, other):
if isinstance(other, MyIntegral):
return do_my_adding_stuff(other, self)
elif isinstance(other, OtherTypeIKnowAbout):
return do_my_other_adding_stuff(other, self)
elif isinstance(other, Integral):
return int(other) + int(self)
elif isinstance(other, Real):
return float(other) + float(self)
elif isinstance(other, Complex):
return complex(other) + complex(self)
else:
return NotImplemented
There are 5 different cases for a mixed-type operation on subclasses
of Complex. All of the above code that doesn’t refer to
MyIntegral and OtherTypeIKnowAbout is referred to as “boilerplate”.
In this description, a is an instance of A and b is an
instance of B, where A and B are both subtypes of Complex.
Consider a + b:
만약
A가b를 받는__add__()메서드를 정의했다면 모든 것이 문제없이 처리됩니다.A가 기본구조 코드로 진입하고__add__()로 부터 어떤 값을 반환한다면B가 똑똑하게 정의한__radd__()메서드를 놓칠 수 있습니다. 이를 피하려면 기본구조는__add__()에서NotImplemented를 반환해야 합니다. (또는A가__add__()메서드를 전혀 구현하지 않을 수도 있습니다.)그다음
B의__radd__()메서드가 기회를 얻습니다. 이 메서드가a를 받을 수 있다면 모든 것이 문제없이 처리됩니다.기본구조 코드로 돌아온다면 더 시도해 볼 수 있는 메서드가 없으므로 기본적으로 수행될 구현을 작성해야 합니다.
If
Bis a subtype ofA, Python triesB.__radd__beforeA.__add__. This is ok, because it was implemented with knowledge ofA, so it can handle those instances before delegating toComplex.
If A is a subtype of Complex and B is a subtype of
Real without sharing any other knowledge, then the appropriate
shared operation is the one involving the built
in complex, and both __radd__() s land there, so a+b
== b+a.
대부분 주어진 어떤 형에 대한 연산은 매우 비슷하므로, 주어진 연산자의 정방향(forward) 인스턴스와 역방향(reverse) 인스턴스를 생성하는 헬퍼 함수를 정의하는 것이 유용합니다. 예를 들어 fractions.Fraction 클래스는 다음과 같이 사용합니다:
def _operator_fallbacks(monomorphic_operator, fallback_operator):
def forward(a, b):
if isinstance(b, (int, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
elif isinstance(b, complex):
return fallback_operator(complex(a), b)
else:
return NotImplemented
forward.__name__ = '__' + fallback_operator.__name__ + '__'
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
if isinstance(a, Rational):
# 정수를 포함합니다.
return monomorphic_operator(a, b)
elif isinstance(a, Real):
return fallback_operator(float(a), float(b))
elif isinstance(a, Complex):
return fallback_operator(complex(a), complex(b))
else:
return NotImplemented
reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
reverse.__doc__ = monomorphic_operator.__doc__
return forward, reverse
def _add(a, b):
"""a + b"""
return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)
__add__, __radd__ = _operator_fallbacks(_add, operator.add)
# ...