在OOP程序設計中,當定義一個class的時候,可從某個現有的class繼承
新的class稱爲子類(Subclass),而被繼承的class稱爲基類、父類或超類(Base class、Super class)
格式:函數
class 子類名(父類名): pass
使用示例spa
class Animal(object): def run(self): print('Animal is running...') class Dog(Animal): pass class Dog1(Animal): def run(self): print('Dog is running...') def run_twice(animal): animal.run() animal.run() dog = Dog() dog.run() #輸出:Animal is running... dog1 = Dog1() dog1.run() #輸出:Dog is running...,執行子類本身的方法 run_twice(Animal()) #輸出:Animal is running... #輸出:Animal is running... run_twice(Dog1()) #輸出:Dog is running... #輸出:Dog is running... #新追加一個子類型Tortoise,而後調用run_twice函數,依然能夠運行 class Tortoise(Animal): def run(self): print('Tortoise is running slowly...') run_twice(Tortoise()) #調用run_twice函數,依然能夠運行,確保傳入的對象有run()方法便可 #輸出:Tortoise is running slowly... #輸出:Tortoise is running slowly...
數據類型判斷
定義一個class實際上就是定義一種數據類型,該數據類型和Python自帶的數據類型,好比str、list、dict徹底同樣
判斷一個變量是不是某個類型能夠用isinstance()判斷
對於isinstance(a, A),則
若是a是A類對象,返回true
若是a是A類子類對象,返回true
其餘都返回false設計
關於繼承
1) 繼承能夠把父類的全部功能都直接拿過來,這樣就沒必要重零作起,子類只須要新增本身特有的方法,也能夠把父類不適合的方法覆蓋重寫
子類經過繼承得到了全部父類的方法(包括__init__方法,若是父類的該方法有參數,則子類建立實例時也要傳參數)
2) 當子類和父類都存在相同的方法時,子類覆蓋了父類的該方法,運行時,老是會調用子類方法,這就是就是多態
3) 繼承還能夠一級一級地繼承下來,就比如從爺爺到爸爸、再到兒子這樣的關係
而任何類,最終均可以追溯到根類object,這些繼承關係看上去就像一顆倒着的樹code
關於多態
調用方只管調用,無論細節,而當新增一種子類時,只要確保方法編寫正確,不用管原來的代碼是如何調用的
說白了,就是無論怎麼追加子類,也不須要修改原來的代碼
這就是著名的"開閉"原則:
對擴展開放:容許子類重寫方法函數
對修改封閉:不重寫,直接繼承父類方法函數對象
靜態語言和動態語言
若是一個方法,要傳入的參數是A類對象,方法內部須要調用該參數的run()方法,則:
對於Java這樣的動態語言,則必定要傳入A類或者其子類對象,不然將沒法調用方法
對於Python這樣的動態語言,則不必定要傳入A類或其子類對象,只需保證傳入的對象有一個run()方法便可
這就是動態語言的"鴨子類型",它並不要求嚴格的繼承體系,一個對象只要"看起來像鴨子,走起路來像鴨子",那它就能夠被看作是鴨子
關於file-like object
Python的"file-like object"就是一種鴨子類型
真正的文件對象都有一個read()方法,但許多對象,只要有read()方法,都被視爲"file-like object"
許多函數接收的參數就是"file-like object",不必定要傳入真正的文件對象,徹底能夠傳入任何實現了read()方法的對象blog