On this page
9.1. 数字—数值抽象 Base Class
2.6 版的新Function。
numbers模块( PEP 3141)定义了数字抽象 Base Class的层次结构,该层次结构逐渐定义了更多操作。此模块中定义的所有类型都无法实例化。
- 类别
numbers.
Number
- 数字层次结构的根。如果只想检查参数* x *是否为数字,而又不关心哪种类型,请使用
isinstance(x, Number)
。
- 数字层次结构的根。如果只想检查参数* x *是否为数字,而又不关心哪种类型,请使用
9.1.1. 数字塔
类别
numbers.
Complex
real
- 抽象。检索此数字的实部。
imag
- 抽象。检索此数字的虚部。
conjugate
( )- 抽象。返回复数共轭。例如
(1+3j).conjugate() == (1-3j)
。
- 抽象。返回复数共轭。例如
类别
numbers.
Real
简而言之,它们是:转换为float,math.trunc(),round(),math.floor(),math.ceil(),divmod(),//
,%
,<
,<=
,>
和>=
。
Real 还提供complex(),real,imag和conjugate()的默认值。
类别
numbers.
Rational
- 子类型Real并添加numerator和denominator属性,这些属性应使用最低的术语。有了这些,它提供了float()的默认值。
numerator
- Abstract.
denominator
- Abstract.
类别
numbers.
Integral
- 子类型Rational,并将转换添加到int。提供float(),numerator和denominator的默认值。为
**
和位字符串操作添加抽象方法:<<
,>>
,&
,^
,|
,~
。
- 子类型Rational,并将转换添加到int。提供float(),numerator和denominator的默认值。为
9.1.2. 给类型实现者的 Comments
实现者应注意使相等的数字相等,并将它们散列为相同的值。如果实数有两个不同的 extensions,这可能是微妙的。例如,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))
9.1.2.1. 添加更多数字 ABC
当然,数字可能还有更多的 ABC,如果排除了添加这些数字的可能性,这将是一个糟糕的等级体系。您可以使用以下方法在Complex和Real之间添加MyFoo
:
class MyFoo(Complex): ...
MyFoo.register(Real)
9.1.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
对Complex的子类进行混合类型操作有 5 种不同的情况。我将引用上面所有未将MyIntegral
和OtherTypeIKnowAbout
称为“样板”的代码。 a
将是A
的实例,它是Complex(a : A <: Complex
)和b : B <: Complex
的子类型。我会考虑a + b
:
Note
如果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)
# ...