• 如果您觉得本站非常有看点，那么赶紧使用Ctrl+D 收藏吧

# Python 中的数字到底是什么？

4周前 (09-05) 25次浏览

PEP原文： https://www.python.org/dev/peps/pep-3141/

PEP标题： PEP 3141 — A Type Hierarchy for Numbers

PEP作者： Jeffrey Yasskin

## 规范

### 数值类

``````class Number(metaclass=ABCMeta): pass
``````

``````class Complex(Number):
"""Complex defines the operations that work on the builtin complex type.

In short, those are: conversion to complex, bool(), .real, .imag,
+, -, *, /, **, abs(), .conjugate(), ==, and !=.

If it is given heterogenous arguments, and doesn't have special
knowledge about them, it should fall back to the builtin complex
type as described below.
"""

@abstractmethod
def __complex__(self):
"""Return a builtin complex instance."""

def __bool__(self):
"""True if self != 0."""
return self != 0

@abstractproperty
def real(self):
"""Retrieve the real component of this number.

This should subclass Real.
"""
raise NotImplementedError

@abstractproperty
def imag(self):
"""Retrieve the real component of this number.

This should subclass Real.
"""
raise NotImplementedError

@abstractmethod
raise NotImplementedError

@abstractmethod
raise NotImplementedError

@abstractmethod
def __neg__(self):
raise NotImplementedError

def __pos__(self):
"""Coerces self to whatever class defines the method."""
raise NotImplementedError

def __sub__(self, other):
return self + -other

def __rsub__(self, other):
return -self + other

@abstractmethod
def __mul__(self, other):
raise NotImplementedError

@abstractmethod
def __rmul__(self, other):
raise NotImplementedError

@abstractmethod
def __div__(self, other):
"""a/b; should promote to float or complex when necessary."""
raise NotImplementedError

@abstractmethod
def __rdiv__(self, other):
raise NotImplementedError

@abstractmethod
def __pow__(self, exponent):
"""a**b; should promote to float or complex when necessary."""
raise NotImplementedError

@abstractmethod
def __rpow__(self, base):
raise NotImplementedError

@abstractmethod
def __abs__(self):
"""Returns the Real distance from 0."""
raise NotImplementedError

@abstractmethod
def conjugate(self):
"""(x+y*i).conjugate() returns (x-y*i)."""
raise NotImplementedError

@abstractmethod
def __eq__(self, other):
raise NotImplementedError

# __ne__ is inherited from object and negates whatever __eq__ does.
``````

`Real`抽象基类表示在实数轴上的值，并且支持内置的`float`的操作。实数（Real number）是完全有序的，除了 NaN（本 PEP 基本上不考虑它）。

``````class Real(Complex):
"""To Complex, Real adds the operations that work on real numbers.

In short, those are: conversion to float, trunc(), math.floor(),
math.ceil(), round(), divmod(), //, %, <, <=, >, and >=.

Real also provides defaults for some of the derived operations.
"""

# XXX What to do about the __int__ implementation that's
# currently present on float?  Get rid of it?

@abstractmethod
def __float__(self):
"""Any Real can be converted to a native float object."""
raise NotImplementedError

@abstractmethod
def __trunc__(self):
"""Truncates self to an Integral.

Returns an Integral i such that:
* i>=0 iff self>0;
* abs(i) <= abs(self);
* for any Integral j satisfying the first two conditions,
abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
i.e. "truncate towards 0".
"""
raise NotImplementedError

@abstractmethod
def __floor__(self):
"""Finds the greatest Integral <= self."""
raise NotImplementedError

@abstractmethod
def __ceil__(self):
"""Finds the least Integral >= self."""
raise NotImplementedError

@abstractmethod
def __round__(self, ndigits:Integral=None):
"""Rounds self to ndigits decimal places, defaulting to 0.

If ndigits is omitted or None, returns an Integral,
otherwise returns a Real, preferably of the same type as
self. Types may choose which direction to round half. For
example, float rounds half toward even.

"""
raise NotImplementedError

def __divmod__(self, other):
"""The pair (self // other, self % other).

Sometimes this can be computed faster than the pair of
operations.
"""
return (self // other, self % other)

def __rdivmod__(self, other):
"""The pair (self // other, self % other).

Sometimes this can be computed faster than the pair of
operations.
"""
return (other // self, other % self)

@abstractmethod
def __floordiv__(self, other):
"""The floor() of self/other. Integral."""
raise NotImplementedError

@abstractmethod
def __rfloordiv__(self, other):
"""The floor() of other/self."""
raise NotImplementedError

@abstractmethod
def __mod__(self, other):
"""self % other

See
https://mail.python.org/pipermail/python-3000/2006-May/001735.html
and consider using "self/other - trunc(self/other)"
"""
raise NotImplementedError

@abstractmethod
def __rmod__(self, other):
"""other % self"""
raise NotImplementedError

@abstractmethod
def __lt__(self, other):
"""< on Reals defines a total ordering, except perhaps for NaN."""
raise NotImplementedError

@abstractmethod
def __le__(self, other):
raise NotImplementedError

# __gt__ and __ge__ are automatically done by reversing the arguments.
# (But __le__ is not computed as the opposite of __gt__!)

# Concrete implementations of Complex abstract methods.
# Subclasses may override these, but don't have to.

def __complex__(self):
return complex(float(self))

@property
def real(self):
return +self

@property
def imag(self):
return 0

def conjugate(self):
"""Conjugate is a no-op for Reals."""
return +self
``````

``````class Rational(Real, Exact):
""".numerator and .denominator should be in lowest terms."""

@abstractproperty
def numerator(self):
raise NotImplementedError

@abstractproperty
def denominator(self):
raise NotImplementedError

# Concrete implementation of Real's conversion to float.
# (This invokes Integer.__div__().)

def __float__(self):
return self.numerator / self.denominator
``````

``````class Integral(Rational):
"""Integral adds a conversion to int and the bit-string operations."""

@abstractmethod
def __int__(self):
raise NotImplementedError

def __index__(self):
"""__index__() exists because float has __int__()."""
return int(self)

def __lshift__(self, other):
return int(self) << int(other)

def __rlshift__(self, other):
return int(other) << int(self)

def __rshift__(self, other):
return int(self) >> int(other)

def __rrshift__(self, other):
return int(other) >> int(self)

def __and__(self, other):
return int(self) & int(other)

def __rand__(self, other):
return int(other) & int(self)

def __xor__(self, other):
return int(self) ^ int(other)

def __rxor__(self, other):
return int(other) ^ int(self)

def __or__(self, other):
return int(self) | int(other)

def __ror__(self, other):
return int(other) | int(self)

def __invert__(self):
return ~int(self)

# Concrete implementations of Rational and Real abstract methods.
def __float__(self):
"""float(self) == float(int(self))"""
return float(int(self))

@property
def numerator(self):
"""Integers are their own numerators."""
return +self

@property
def denominator(self):
"""Integers have a denominator of 1."""
return 1
``````

### 运算及__magic__方法的变更

1. __trunc__(self)：在新的内置 trunc(x) 里调用，它返回从 0 到 x 之间的最接近 x 的 Integral。
2. __floor__(self)：在 math.floor(x) 里调用，返回最大的 Integral <= x。
3. __ceil__(self)：在 math.ceil(x) 里调用，返回最小的 Integral > = x。
4. __round__(self)：在 round(x) 里调用，返回最接近 x 的 Integral ，根据选定的类型作四舍五入。浮点数将从 3.0 版本起改为向偶数端四舍五入。（译注：round(2.5) 等于 2，round(3.5) 等于 4）。它还有一个带两参数的版本__round__(self, ndigits)，被 round(x, ndigits) 调用，但返回的是一个 Real。

float 的 int() 转换等效于 trunc()。一般而言，int() 的转换首先会尝试__int__()，如果找不到，再尝试__trunc__()。

complex.__{divmod, mod, floordiv, int, float}__ 也消失了。提供一个好的错误消息来帮助困惑的搬运工会很好，但更重要的是不出现在 help(complex) 中。

### 给类型实现者的说明

``````def __hash__(self):
return hash(complex(self))
``````

#### 添加更多数字抽象基类

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

#### 实现算术运算

``````class MyIntegral(Integral):

if isinstance(other, MyIntegral):
else:
return NotImplemented

if isinstance(other, MyIntegral):
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
``````

a 是 A 的实例，它是`Complex(a : A <: Complex)` 的子类型，还有 `b : B <: Complex`。对于 a + b，我这么考虑：

1. 如果 A 定义了接受 b 的__add__，那么没问题。
4. 如果它走到样板分支上，就没有办法了，因此需要有默认的实现。
5. 如果 B <: A，则 Python 会在 A.__ add__之前尝试 B.__ radd__。这也可以，因为它是基于 A 而实现的，因此可以在委派给 Complex 之前处理这些实例。

## 参考文献

1、抽象基类简介：http://www.python.org/dev/peps/pep-3119/

2、可能是 Python 3 的类树？Bill Janssen 的 Wiki 页面：http://wiki.python.org/moin/AbstractBaseClasses

4、Scheme 数字塔：https://groups.csail.mit.edu/mac/ftpdir/scheme-reports/r5rs-html/r5rs_8.html#SEC50

（译注：在译完之后，我才发现“PEP中文翻译计划”已收录过一篇译文，有些地方译得不尽相同，读者们可比对阅读。）