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