numbersNumeric abstract base classes数字抽象基类

Source code: Lib/numbers.py


The numbers module (PEP 3141) defines a hierarchy of numeric abstract base classes which progressively define more operations. numbers模块(PEP 3141)定义了数字抽象基类的层次结构,这些基类逐步定义了更多操作。None of the types defined in this module are intended to be instantiated.本模块中定义的任何类型都不打算实例化。

classnumbers.Number

The root of the numeric hierarchy. 数字层次结构的根。If you just want to check if an argument x is a number, without caring what kind, use isinstance(x, Number).如果您只想检查参数x是否是数字,而不关心是什么类型,请使用isinstance(x, Number)

The numeric tower数字塔

classnumbers.Complex

Subclasses of this type describe complex numbers and include the operations that work on the built-in complex type. 这种类型的子类描述复数,并包括处理内置complex类型的操作。These are: conversions to complex and bool, real, imag, +, -, *, /, **, abs(), conjugate(), ==, and !=. 这些是:complexboolrealimag+-*/**abs()conjugate()(共轭)、==、和!=All except - and != are abstract.-!=都是抽象的。

real

Abstract. 摘要Retrieves the real component of this number.检索此数字的真实分量。

imag

Abstract. Retrieves the imaginary component of this number.摘要检索此数字的虚部。

abstractmethodconjugate()

Abstract. 摘要Returns the complex conjugate. 返回复数共轭。For example, (1+3j).conjugate() == (1-3j).例如,(1+3j).conjugate() == (1-3j)

classnumbers.Real

To Complex, Real adds the operations that work on real numbers.对于ComplexReal加上了对实数的运算。

In short, those are: a conversion to float, math.trunc(), round(), math.floor(), math.ceil(), divmod(), //, %, <, <=, >, and >=.简而言之,它们是:到floatmath.trunc()round()math.floor()math.ceil()divmod()//%<<=>>=的转换。

Real also provides defaults for complex(), real, imag, and conjugate().实数还为complex()realimagconjugate()提供默认值。

classnumbers.Rational

Subtypes Real and adds numerator and denominator properties, which should be in lowest terms. 子类型为Real,并添加numerator(分子)和denominator(分母)属性,这些属性应为最低值。With these, it provides a default for float().有了这些,它为float()提供了一个默认值。

numerator

Abstract.摘要

denominator

Abstract.摘要

classnumbers.Integral

Subtypes Rational and adds a conversion to int. 子类型为Rational并添加到int的转换。Provides defaults for float(), numerator, and denominator. 提供float()numeratordenominator的默认值。Adds abstract methods for pow() with modulus and bit-string operations: <<, >>, &, ^, |, ~.为具有模和位字符串操作的pow()添加抽象方法:<<>>&^|

Notes for type implementors类型实现者注意事项

Implementors should be careful to make equal numbers equal and hash them to the same values. 实现者应该小心地使相等的数字相等,并将它们散列为相同的值。This may be subtle if there are two different extensions of the real numbers. 如果实数有两种不同的扩展,这可能很微妙。For example, fractions.Fraction implements hash() as follows:例如,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))

Adding More Numeric ABCs添加更多数字ABC

There are, of course, more possible ABCs for numbers, and this would be a poor hierarchy if it precluded the possibility of adding those. 当然,对于数字来说,有更多可能的ABC,如果它排除了添加这些ABC的可能性,那么这将是一个糟糕的层次结构。You can add MyFoo between Complex and Real with:您可以使用以下工具在ComplexReal之间添加MyFoo

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

Implementing the arithmetic operations实现算术运算

We want to implement the arithmetic operations so that mixed-mode operations either call an implementation whose author knew about the types of both arguments, or convert both to the nearest built in type and do the operation there. 我们想要实现算术运算,这样混合模式运算要么调用作者知道两个参数类型的实现,要么将两者转换为最近的内置类型并在那里执行运算。For subtypes of Integral, this means that __add__() and __radd__() should be defined as:对于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

There are 5 different cases for a mixed-type operation on subclasses of Complex. 对于Complex的子类,混合类型操作有5种不同的情况。I’ll refer to all of the above code that doesn’t refer to MyIntegral and OtherTypeIKnowAbout as “boilerplate”. 我将引用上述所有代码,这些代码没有将MyIntegralOtherTypeIKnowAbout称为“样板”。a will be an instance of A, which is a subtype of Complex (a : A <: Complex), and b : B <: Complex. a将是A的实例,aComplexa : A <: Complex)的子类型,并且b : B <: ComplexI’ll consider a + b:我会考虑a+b

  1. If A defines an __add__() which accepts b, all is well.如果A定义了一个接受b__add__(),则一切正常。

  2. 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__(). 如果A返回到样板代码,并从__add__()返回一个值,我们将错过B定义更智能的__radd__()的可能性,因此样板应该从__add__()返回NotImplemented(Or A may not implement __add__() at all.)(或者A可能根本无法实现__add__()

  3. Then B’s __radd__() gets a chance. 然后B__radd__()得到了一个机会。If it accepts a, all is well.如果它接受a,一切都好。

  4. If it falls back to the boilerplate, there are no more possible methods to try, so this is where the default implementation should live.如果回到样板文件,就没有更多可能的方法可以尝试,因此这就是默认实现应该存在的地方。

  5. If B <: A, Python tries B.__radd__ before A.__add__. 如果B<: A,Python在A.__add__.之前尝试B.__radd__This is ok, because it was implemented with knowledge of A, so it can handle those instances before delegating to Complex.这没关系,因为它是在了解A的情况下实现的,所以它可以在委托给Complex之前处理这些实例。

If A <: Complex and B <: Real without sharing any other knowledge, then the appropriate shared operation is the one involving the built in complex, and both __radd__() s land there, so a+b == b+a.如果A <: ComplexB <: Real没有共享任何其他知识,那么适当的共享操作是涉及内置complex的操作,并且两个__radd__()都在那里,因此a+b == b+a

Because most of the operations on any given type will be very similar, it can be useful to define a helper function which generates the forward and reverse instances of any given operator. 由于任何给定类型上的大多数操作都非常相似,因此定义一个辅助函数非常有用,该函数可以生成任何给定运算符的正向和反向实例。For example, fractions.Fraction uses:例如,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)

# ...