numbers ---数字抽象基类¶
源代码: Lib/numbers.py
这个 numbers 模块 (PEP 3141 )定义数字的层次结构 abstract base classes 逐步定义更多的操作。不能实例化此模块中定义的任何类型。
- 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¶
-
简而言之,这些是:转换为
float,math.trunc(),round(),math.floor(),math.ceil(),divmod(),//,%,<,<=,>,以及>=。real还提供
complex(),real,imag和conjugate().
类型实现者注意事项¶
实现人员应该小心地使相等的数字相等,并将它们散列为相同的值。如果实数有两个不同的扩展,这可能很微妙。例如, 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))
添加更多的数字ABC¶
当然,对于数字来说,可能有更多的ABC,如果排除了添加这些ABC的可能性,这将是一个糟糕的层次结构。您可以添加 MyFoo 之间 Complex 和 Real 用:
class MyFoo(Complex): ...
MyFoo.register(Real)
实现算术运算¶
我们希望实现算术运算,这样混合模式运算要么调用一个实现,该实现的作者知道这两个参数的类型,要么将这两个参数都转换为最近的内置类型并在其中执行运算。对于subtype 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 <: APython尝试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, 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)
# ...