《零基礎入門學習Python》(43)魔法方法:算術運算(2)
前言:
上節課我們介紹了很多關於計算的魔法方法,當你的物件進行了相關的算術操作的時候,自然而然就會觸發相應的魔法方法,一旦你重寫了這些魔法方法,那麼Python就會根據你的意圖進行計算。
通過對相關的魔法方法進行重寫,可以讓Python根據你的意圖執行程式。
這裡我們就讓加變成減
>>> class int(int): def __add__(self,other): return int.__sub__(self,other) >>> a=int('5') >>> a 5 >>> b=int('3') >>> a+b 2
知識點—— [擴充套件閱讀] Python 魔法方法詳解
1.反運算 __radd__(self, other) (與上方相同,當左運算元不支援相應的操作時被呼叫)
>>> class Nint(int): def __radd__(self,other): return int.__sub__(self,other) >>> a=Nint(5) >>> b=Nint(6) >>> a+b 11 >>> 1+b #因為找不到1的add方法,所以就找到b的add方法,然後就觸發b的radd方法,然後執行了一個sub方法用6-1 #self指定是b,other指的是self方法 5
2._rsub__(self, other) (與上方相同,當左運算元不支援相應的操作時被呼叫)
>>> class Nint(int):
def __rsub__(self,other):
return int.__sub__(self,other)
>>> a=Nint(5)
>>> 3-a#和上一個程式碼同理
2
#改成熟悉的順序。。。。
class Nint(int):
def __rsub__(self,other):
return int.__sub__(other,self)
3.__iadd__(self, other) 定義賦值加法的行為:+=#操作同上
其他相關的魔法方法很多的相似,我就不在這列出來了,需要更多的魔法方法去開始給的連結處檢視
測試題:
0.物件相加(a+b),如果a物件有__add__方法,請問b物件的__radd__會被呼叫嘛?
答:不會!
>>> class Nint(int):
def __radd__(self,other):
print("__radd__被呼叫")
return int.__add__(self,other)
>>> a=Nint(5)
>>> b=Nint(3)
>>> a+b
8
>>> 1+b
__radd__被呼叫
4
1.python什麼時候會呼叫到煩運算的魔法方法?
答:例如a+b,如果a物件的__add__方法沒有實現或者不支援相應的操作,那麼Python就會自動呼叫b的__radd__方法。
2.請問如何在繼承的類中呼叫基類的方法?
答:使用super()這個BIF函式。
>>> class Derived(Base):
def meth(self):
super(Derived,self).meth()
3.如果我要繼承的基類是動態的(有時是A,有時是B),我應該如何部署我的程式碼,以便基類可以隨意改變?
答:你可以先為基類定義一個別名,在類定義的時候,使用別名代替你要繼承的基類。如此,當你想要改變基類的時候,只需要修改給別名賦值的那個語句即可。順便說一下,當你的資源是視情況而定的時候,這個小技巧很管用。
BaseAlias = BaseClass#為基類取別名
class Derived(BaseClass):
def meth(self):
BaseAlias.meth(self)#通過別名訪問基類
.........
4.嘗試自己舉一個例子說明如何使用類的靜態方法
答:類的靜態屬性很簡單,在類中直接定義的變數(self)就是靜態屬性。引用的靜態屬性使用“類名.屬性名”的形式。
#類的靜態屬性使用
>>> class C:
count = 0
def __init__(self):
C.count = C.count+1
def getCount(self):
return C.count
5. 嘗試自己舉例說明如何使用類的靜態方法,並指出使用類的靜態方法有何有點和需要注意的地方?(一定要自己先動手再看答案哦^_^)
答:靜態方法是類的特殊方法,靜態方法只需要在普通方法的前邊加上 @staticmethod 修飾符即可。
>>> class C:
@staticmethod # 該修飾符表示 static() 是靜態方法
def static(arg1, arg2, arg3):
print(arg1, arg2, arg3, arg1 + arg2 + arg3)
def nostatic(self):
print("I'm the f**king normal method!")
>>> c1=C()
>>> c2=C()
>>> c1.static is C.static
True
>>> c1.nostatic is C.nostatic
False
>>> c1.static
<function C.static at 0x03FAAC00>
>>> c2.static
<function C.static at 0x03FAAC00>
>>> C.static
<function C.static at 0x03FAAC00>
# 普通方法每個例項物件都擁有獨立的一個,開銷較大
>>> c1.nostatic
<bound method C.nostatic of <__main__.C object at 0x03F96470>>
>>> c2.nostatic
<bound method C.nostatic of <__main__.C object at 0x03F96910>>
>>> C.nostatic
<function C.nostatic at 0x03FAAC48>
使用的時候需要注意的地方:靜態方法並不需要 self 引數,因此即使是使用物件去訪問,self 引數也不會傳進去。
>>> c1.static(1, 2, 3)
1 2 3 6
>>> C.static(1, 2, 3)
1 2 3 6
動動手
0. 定義一個類,當例項化該類的時候,自動判斷傳入了多少個引數,並顯示出來。z
答:其實很容易啦,檢查下大家之前的知識點有沒有記牢固而已。
class C:
def __init__(self, *args):
if not args:
print("並沒有傳入引數")
else:
print("傳入了 %d 個引數,分別是:" % len(args), end='')
for each in args:
print(each, end=' ')
1. 定義一個單詞(Word)類繼承自字串,重寫比較操作符(參考自學:Python 魔法方法詳解),當兩個 Word 類物件進行比較時,根據單詞的長度來進行比較大小。
加分要求:例項化時如果傳入的是帶空格的字串,則取第一個空格前的單詞作為引數。
答:加分要求可以通過過載 __new__ 方法來實現(因為字串是不可變型別),通過重寫 __gt__、__lt__、__ge__、__le__ 方法來定義 Word 類在比較操作中的表現。
注意,我們沒有定義 __eq__ 和 __ne__ 方法。這是因為將會產生一些怪異不符合邏輯的結果(比如 Word('FishC') 會等於 Word('Apple'))
class Word(str):
'''儲存單詞的類,定義比較單詞的幾種方法'''
def __new__(cls, word):
# 注意我們必須要用到 __new__ 方法,因為 str 是不可變型別
# 所以我們必須在建立的時候將它初始化
if ' ' in word:
print "Value contains spaces. Truncating to first space."
word = word[:word.index(' ')] #單詞是第一個空格之前的所有字元
return str.__new__(cls, word)
def __gt__(self, other):
return len(self) > len(other)
def __lt__(self, other):
return len(self) < len(other)
def __ge__(self, other):
return len(self) >= len(other)
def __le__(self, other):
return len(self) <= len(other)