numbers

numbers — Numeric abstract base classes

2.6版本中的新功能。

所述numbers模块(PEP 3141)定义的数值的层次抽象基类,其渐进地限定多个操作。本模块中定义的任何类型都不能实例化。

class numbers.Number

数字层次结构的根。如果你只是想检查一个参数x是否是一个数字,而不关心什么样的话,那就使用isinstance(x, Number)

数字塔

class numbers.Complex

这种类型的子类描述了复数,并包含了对内建complex类型起作用的操作。它们是:转换到complexboolrealimag+-*/abs()conjugate()==,和!=。所有除了-!=是抽象的。

real

抽象。检索此数字的实际组成部分。

imag

抽象。检索这个数字的虚部。

conjugate()

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

class numbers.Real

ComplexReal增加了对实数起作用的操作。

总之,这些是:一次转化float,math.trunc(),round(),math.floor(),math.ceil(),divmod(),//,%,<,<=,>,和>=。

真正还提供了默认值complex()realimag,和conjugate()

class numbers.Rational

子类型Real和增加numeratordenominator属性,应该是最低的。有了这些,它提供了一个默认值float()

numerator

抽象。

denominator

抽象。

class numbers.Integral

子类型Rational并向其添加转换int。提供了默认值float(),numerator和denominator。增加了对抽象方法**和比特字符串操作:<<,>>,&,^,|,~。

2.类型实现者的注释

实现者应该小心地使相等的数字相等并将它们散列为相同的值。如果有两个不同的实数扩展名,这可能很微妙。例如,fractions.Fraction实现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))

2.1。添加更多数字ABCs

当然,对于数字来说,有更多可能的ABC,如果它排除了添加这些数字的可能性,这将是一个糟糕的等级。你可以添加和MyFoo之间:ComplexReal

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

2.2。实现算术运算

我们希望实现算术运算,以便混合模式操作或者调用作者知道两个参数类型的实现,或者将两者都转换为最接近的内置类型并在那里执行操作。对于子类型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

对于子类的混合类型操作有5种不同的情况Complex。我将参考上述所有没有提及的代码,MyIntegral并将其OtherTypeIKnowAbout作为“样板”。a将是一个实例A,它是Complex(a : A <: Complex),和的子类型b : B <: Complex。我会考虑a + b:

  • 如果A定义一个__add__()接受b,一切都很好。

  • 如果A退回到样板代码,并从中返回一个值__add__(),我们会错过B定义更智能的可能性__radd__(),所以样板应该NotImplemented从中返回__add__()。(或者A可能根本没有实施__add__()。)

  • 随后B__radd__()得到一个机会。如果它接受a,一切都很好。

  • 如果它回落到样板,则没有更多可能的方法来尝试,所以这是默认实现应该存在的地方。

  • 如果B <: A,Python尝试B.__radd__之前A.__add__。这是可以的,因为它是在知道的情况下实现的A,所以它可以在委托之前处理这些实例Complex。

如果A <: Complex和B <: Real没有分享任何其他知识,那么适当的共享操作就是内置的操作complex,并且两者都__radd__()在那里,所以a+b == b+a。

因为任何给定类型的大多数操作都非常相似,所以定义一个辅助函数会很有用,它可以生成任何给定操作符的正向和反向实例。例如,fractions.Fraction使用:

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) # ...