Python基礎學習:numbers模組
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)