版本 2.6 新增。
numbers 模块 (PEP 3141) 定义层次结构,数字的抽象基类,这些类逐步定义更多的操作。本模块中定义的任何类型,都不能被实例化。
数字层次结构的根。如果您只想检查参数 x 是否是数字(而不关心它是哪一种),请使用 isinstance(x, Number)。
这种类型的子类描述复数和包括工作的内置复数类型的操作。这些都是: 转换为复数和布尔,实数、虚数、 +、 -、 *、 /、 abs()、 conjugate()、 = =,和! =。所有除-和! =都是抽象的。
抽象。检索此数的实数分量。
抽象。检索此数的虚数分量。
抽象。返回共轭复数。例如, (1+3j).conjugate() = = (1-3j)。
简而言之,这些转换操作包括:float(), math.trunc(), round(), math.floor(), math.ceil(), divmod()、 / /, %, <, < =, >,和> =。
实也为complex()、真实、形象、 和conjugate()提供默认值。
执行者要小心使相等的数字相等和散列他们为相同的值。这可能是实数的微妙的如果有两个不同的扩展。例如,分数。分数实现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))
当然,有数字,更有可能基本要领,如果它排除了那些增加的可能性,这将是糟糕的层次结构。您可以添加MyFoo之间复数而实数的:
class MyFoo(Complex): ...
MyFoo.register(Real)
我们想要实现的算术运算,以便混合模式操作调用的作者知道这两个参数的类型的实现或都转换为最近内建类型和那里操作。对于亚型的积分,这意味着__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 对子类的复数的混合型操作不同的情况。我将提及所有上面的代码并不是指MyIntegral和OtherTypeIKnowAbout作为"样板"。将实例A,这是一种亚型复杂( : A <: 复杂),和b : B <: 复杂。我会考虑 + b:
- If A defines an __add__() which accepts b, all is well.
- 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.)
- Then B‘s __radd__() gets a chance. If it accepts a, all is well.
- If it falls back to the boilerplate, there are no more possible methods to try, so this is where the default implementation should live.
- 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)
# ...