# 9.1. `numbers` — 数字的抽象基类¶

2.6 新版功能.

`numbers` 模块 (PEP 3141) 定义了数字 抽象基类 的层次结构，其中逐级定义了更多操作。 此模块中所定义的类型都不可被实例化。

class `numbers.``Number`

## 9.1.1. 数字的层次¶

class `numbers.``Complex`

`real`

`imag`

`conjugate`()

class `numbers.``Real`

class `numbers.``Rational`

`numerator`

`denominator`

class `numbers.``Integral`

## 9.1.2. 类型接口注释。¶

```def __hash__(self):
if self.denominator == 1:
# Get integers right.
return hash(self.numerator)
# Expensive check, but definitely correct.
if self == float(self):
return hash(float(self))
else:
# Use tuple's hash to avoid a high collision rate on
# simple fractions.
return hash((self.numerator, self.denominator))
```

### 9.1.2.1. 加入更多数字的ABC¶

```class MyFoo(Complex): ...
MyFoo.register(Real)
```

### 9.1.2.2. 实现算数运算¶

```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`. I’ll refer to all of the above code that doesn’t refer to `MyIntegral` and `OtherTypeIKnowAbout` as “boilerplate”. `a` will be an instance of `A`, which is a subtype of `Complex` (`a : A <: Complex`), and ```b : B <: Complex```. I’ll consider `a + b`:

1. 如果 `A` 被定义成一个承认``b`` 的 `__add__()`，一切都没有问题。

2. 如果 `A` 转回成“模板”失败，它将返回一个属于 `__add__()` 的值，我们需要避免 `B` 定义了一个更加智能的 `__radd__()`，因此模板需要返回一个属于 `__add__()``NotImplemented` 。（或者 `A` 可能完全不实现 `__add__()` 。）

3. 接着看 `B``__radd__()` 。如果它承认 `a` ，一切都没有问题。

4. 如果没有成功回退到模板，就没有更多的方法可以去尝试，因此这里将使用默认的实现。

5. 如果 `B <: A` ， Python 在 `A.__add__` 之前尝试 `B.__radd__` 。 这是可行的，是通过对 `A` 的认识实现的，因此这可以在交给 `Complex` 处理之前处理这些实例。

```def _operator_fallbacks(monomorphic_operator, fallback_operator):
def forward(a, b):
if isinstance(b, (int, long, 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):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
return fallback_operator(float(a), float(b))
elif isinstance(a, numbers.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)

# ...
```