9.1. numbers数字的抽象基类

版本 2.6 新增。

numbers 模块 (PEP 3141) 定义层次结构,数字的抽象基类,这些类逐步定义更多的操作。本模块中定义的任何类型,都不能被实例化。

class numbers.Number

数字层次结构的根。如果您只想检查参数 x 是否是数字(而不关心它是哪一种),请使用 isinstance(x, Number)

9.1.1. The numeric tower

class numbers.Complex

这种类型的子类描述复数和包括工作的内置复数类型的操作。这些都是: 转换为复数布尔实数虚数 + - * / abs() conjugate() = =,和! =所有除-! =都是抽象的。

real

抽象。检索此数的实数分量。

imag

抽象。检索此数的虚数分量。

conjugate()

抽象。返回共轭复数。例如, (1+3j).conjugate() = = (1-3j)

class numbers.Real

能把实数操作添加至 复数实数

简而言之,这些转换操作包括:float(), math.trunc(), round(), math.floor(), math.ceil(), divmod() / / % < < = >,和> =

实也为complex()真实形象、 和conjugate()提供默认值。

class numbers.Rational

亚型真实和添加分子分母的属性,应在最低条款。有了这些,它为float()提供默认值。

numerator

摘要。

denominator

摘要。

class numbers.Integral

亚型 有理数,并添加转换为int 类型float()分子分母提供默认值。添加*和位字符串运算的抽象方法: << >> & ^ | ~

9.1.2. Notes for type implementors

执行者要小心使相等的数字相等和散列他们为相同的值。这可能是实数的微妙的如果有两个不同的扩展。例如,分数。分数实现hash() ,如下所示:

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. Adding More Numeric ABCs

当然,有数字,更有可能基本要领,如果它排除了那些增加的可能性,这将是糟糕的层次结构。您可以添加MyFoo之间复数实数的:

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

9.1.2.2. 数值计算的实现

我们想要实现的算术运算,以便混合模式操作调用的作者知道这两个参数的类型的实现或都转换为最近内建类型和那里操作。对于亚型的积分,这意味着__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

有 5 对子类的复数的混合型操作不同的情况。我将提及所有上面的代码并不是指MyIntegralOtherTypeIKnowAbout作为"样板"。将实例A,这是一种亚型复杂( A <: 复杂),和b B <: 复杂我会考虑 + b

  1. If A defines an __add__() which accepts b, all is well.
  2. If A falls back to the boilerplate code, and it were to return a value from __add__(), we’d miss the possibility that B defines a more intelligent __radd__(), so the boilerplate should return NotImplemented from __add__(). (Or A may not implement __add__() at all.)
  3. Then B‘s __radd__() gets a chance. If it accepts a, all is well.
  4. If it falls back to the boilerplate, there are no more possible methods to try, so this is where the default implementation should live.
  5. If B <: A, Python tries B.__radd__ before A.__add__. This is ok, because it was implemented with knowledge of A, so it can handle those instances before delegating to Complex.

如果A <: 复杂B <: 真正而不共享任何其他知识,则相应的共享的操作是一个涉及的内置的复杂,和两个__radd__()的土地在那里,所以a + b = = b + a

由于大多数任何给定类型操作会很相似,因此,它能定义可生成任何给定操作正反向实例的 helper 函数。例如,分数。分数使用:

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)

# ...