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)