標籤:序列 div 16px style 鴨子類型 int 特性 定義 read
多態的概念
多態指的是一類事物的多種形態,例如水有固態、液態、氣態,動物有人、狗、豬,這是動物的不同形態。可能你會領悟,人狗豬不是繼承於動物類嗎?沒錯,多態在程式中的表現形式就是依賴於繼承
多態性
那多態到底有什麼特性呢?多態性指的是可以在不用考慮對象具體類型的前提下,直接使用對象下的方法,也就是說,繼承同一個類的多個子類有相同的方法名,那麼子類產生的對象就可以不用考慮具體的類型而直接調用對象的方法
舉一個例子,動物有人狗豬,動物都會叫,那麼人狗豬也都會叫,只不過叫的方式不同
class Animal: passclass People(Animal): def speak(self): print(‘say hello‘)class Dog(Animal): def speak(self): print(‘汪汪汪‘)class Pig(Animal): def speak(self): print(‘哼哼哼‘)# peo、dog、pig都是動物, 只要是動物肯定有speak方法# 於是我們可以不用考慮它們三者的具體是什麼類型, 而直接使用peo = People()dog1 = Dog()pig1 = Pig()peo.speak()dog1.speak()pig1.speak()
View Code
但是美中不足的是,如果現在人的叫不寫成 speak ,寫成 talk,那麼便無法遵循父類的方法去實現多態性,如果這三個都想實現叫的功能,父類要有,子類也要有,這顯然很麻煩,並且這樣寫不能對子類有個強制性的限制,這個限制是子類必須有一個叫的功能,這個功能是 speak。於是要寫一個解決方案,強制子類遵循父類的標準,有一個 abc 的模組,可以實現這個功能
import abcclass Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def speak(self): passclass People(Animal): # def speak(self): # print(‘say hello‘) # 寫成talk便會報錯 def talk(self): print(‘say hello‘)class Dog(Animal): def speak(self): print(‘汪汪汪‘)class Pig(Animal): def speak(self): print(‘哼哼哼‘)peo = People()dog1 = Dog()pig1 = Pig()peo.speak()dog1.speak()pig1.speak()# 運行TypeError: Can‘t instantiate abstract class People with abstract methods speak
View Code
鴨子類型
但是上面所說的這些並不是 Python 所推崇的,Python 崇尚的是 “鴨子類型” ,即 “如果看起來像鴨子、叫聲像鴨子而且走起路來也像鴨子,那麼它就是鴨子”,
Python 程式員通常根據這種行為來編寫程式。例如,如果想編寫現有對象的自訂版本,可以繼承該對象,也可以建立一個外觀和行為像,但與它無任何關係的全新對象,後者通常用於儲存程式組件的解耦合度
# 利用標準庫中定義的各種‘與檔案類似’的對象,儘管這些對象的工作方式像檔案,但他們沒有繼承內建檔案對象的方法# 二者都像鴨子,二者看起來都像檔案,因而就可以當檔案一樣去用class TxtFile: def read(self): pass def write(self): passclass DiskFile: def read(self): pass def write(self): pass# 例2:其實大家一直在享受著多態性帶來的好處,比如Python的序列類型有多種形態:字串,列表,元組,多態性體現如下# str,list,tuple都是序列類型s=str(‘hello‘)l=list([1,2,3])t=tuple((4,5,6))# 我們可以在不考慮三者類型的前提下使用s,l,ts.__len__()l.__len__()t.__len__()len(s)len(l)len(t)
View Code
物件導向之多態