numbers——数字抽象基类,其源代码存储在:Lib/numbers.py
numbers模块定义了数字抽象基类的层次结构,逐渐定义更多的操作。该模块中定义的任何类型都不能实例化。
1.数字塔
class numbers.Complex
数字的一个子类,用来描述复数以及可应用于内置复数类型的操作中。它们是:complex(复数)转化、bool(布尔)、real(复数实部)、image(复数虚部)、+、-、*、/、abs()、conjugate(将实部与虚部连接起来,构成完整复数)、==、和!=。上述操作除了-和!=都是抽象操作。
class numbers.Rational
实数的子类有理数,它具有额外的numerator(分子)、denominator(分母)属性并且,它为float()提供了默认值。
class numbers.Integral
有理数的子类,添加了整型转化方法。默认提供了float()、分子与分母。额外的抽象方法由**,字符位操作:<<、>>、&、^、|、~。
2.类型实现器注解
实现器应当谨慎的运行,使得相等数值的数字相等(跨越子类型),并且使它们散列为相同的值。如果两个实数存有不同的扩展名,该实现器应当能打破这种微妙的处境,实现结果的输出。例如,fractions.Fraction应用hash()操作,示例如下
def__hash__(self):
ifself.denominator ==1:
# Get integers right.
returnhash(self.numerator)
# Expensive check, but definitely correct.
ifself==float(self):
returnhash(float(self))
else:
# Use tuple's hash to avoid a high collision rate on
# simple fractions.
returnhash((self.numerator, self.denominator))
2.1 添加更多的数字ABCs(创造新的数字子类)
当然,实际应用中可能需要更多类型的数字,但是由于其比较少见该语言没有内置,因此用户可以自行进行定义添加。比如,你可以添加MyFoo这个介于复数和实数之间的数,利用如下代码:
classMyFoo(Complex): ...
MyFoo.register(Real)
2.2 算数运算的实现
我们希望可以实现算数运算以便于在混合操作中调用编程人员熟知的具有多参数的操作,或者是在操作中将参与运算的参数转化为与其最为相似的内置类型,并执行一般运算操作。对于Integral的子类,这意味着其包含的__add__()和__radd__()方法应该按下述程序定义:
classMyIntegral(Integral):
def__add__(self, other):
ifisinstance(other, MyIntegral):
return do_my_adding_stuff(self, other)
elifisinstance(other, OtherTypeIKnowAbout):
return do_my_other_adding_stuff(self, other)
else:
returnNotImplemented
def__radd__(self, other):
ifisinstance(other, MyIntegral):
return do_my_adding_stuff(other, self)
elifisinstance(other, OtherTypeIKnowAbout):
return do_my_other_adding_stuff(other,self)
elifisinstance(other, Integral):
returnint(other) +int(self)
elifisinstance(other, Real):
returnfloat(other) +float(self)
elifisinstance(other, Complex):
returncomplex(other) +complex(self)
else:
returnNotImplemented
复数的子类上的混合操作有五种情况。前述的代码中除去MyIntegral和OtherTypeIKnow的文本将作为下面描述的样板。a是A的实例,并且使复数的子类(a:A<:Complex),b是B的实例,也是复数的子类。我们以a+b做如下讨论:
1.如果A定义了一个可以接受B的__add__()方法,一切都会是正常的;
2.如果A退回样板代码,它会返回来自于__add__()的值,我们有可能返回更加高级智能的__radd__(),因此样板应当从__add__()返回NotImplemented;
3.然后B中的__radd__()会获得机会,如果其接受a,那么一切都将完美;
4.如果它退回样板代码,那就没有更多的方法用来尝试解决这个问题,因此就要在此设置默认操作;
5.如果B<:A,Python就会先尝试B.__Radd__()方法,再尝试A.__add__()方法。这可以进行,因为操作是在A已知的情况下进行,因此他可以在将这些实例委托给复数类前进行操作。
如果A<:Complex(A为复数子类)、B<:Real(B为实数子类),它们之间没有共享其它信息时,最适合它们的操作就是使用复数操作,所有的__radd__()方法都在复数类中定义了,此时a+b=b+a。
由于大多数类型的运算都十分相似,因此定义一个产生任何给定算子的正向和反向实例的辅助函数会很有用。例如,fractions.Fraction使用了以下代码:
def_operator_fallbacks(monomorphic_operator, fallback_operator):
defforward(a, b):
ifisinstance(b, (int, Fraction)):
return monomorphic_operator(a, b)
elifisinstance(b, float):
return fallback_operator(float(a), b)
elifisinstance(b, complex):
return fallback_operator(complex(a), b)
else:
returnNotImplemented
forward.__name__='__'+ fallback_operator.__name__+'__'
forward.__doc__= monomorphic_operator.__doc__
defreverse(b, a):
ifisinstance(a, Rational):
# Includes ints.
return monomorphic_operator(a, b)
elifisinstance(a, numbers.Real):
return fallback_operator(float(a), float(b))
elifisinstance(a, numbers.Complex):
return fallback_operator(complex(a), complex(b))
else:
returnNotImplemented
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)