面向對象三大特性(*****)1繼承 1. 什麼是繼承 繼承是一種新建類的方式,新建的類稱之爲子類/派生類,被繼承的類稱之爲父類/基類/超類 繼承與現實生活中的繼承一個意思 (例如 小明繼承小明他爹財產 房子) 一個東西b繼承了另外一個東西a b就擁有a的內容 在代碼中 一個類b繼承了另外一個類a b這個類 就擁有了a中全部屬性 繼承有3個特色: 1. 子類能夠遺傳/重用父類的屬性(解決類與類之間代碼冗餘的問題) 2. 在python中一個子類能夠同時繼承多個父類 3. 在繼承的背景下,類分爲兩種:新式類,經典類 新式類:但凡繼承object類的子類,以及該子類的子子孫孫都是新式類 在python3中一個類即使是沒有顯式地繼承任何類,默認就繼承object類, 即在python3中全部類都是新式類 經典類:沒有繼承object類的子類,以及該子類的子子孫孫都是經典類 強調:只有在python2中才有經典類 在python2中若是一個類沒有顯式地繼承任何類,並不會自動繼承object類 2. 爲什麼要用繼承:減小類與類之間的代碼冗餘 使用場景: 例如: 你的項目中須要兩種對象 老師和學生 分析發現 老師和學生有不少類似之處 都有 姓名 性別 年齡 將相同的部分屬性 抽取到一個共同父類中person 3. 如何繼承 :先抽象再繼承(抽取比較像的部分繼承屬性) # 在python中繼承的特色?單繼承(用一個父類)&多繼承(用多個父類) class Person: 共有的屬性 name age gender def sleep(): print(你們都須要睡覺 睡覺的過程也相同) def attendClass(): print("聽到上課鈴聲 要去教室") =================== x = 2 class Foo: x = 1 pass obj = Foo() obj.x = 3 print(obj.x)2 抽象類 什麼是抽象類 ** 與java同樣,python也有抽象類的概念可是一樣須要藉助模塊實現, 抽象類是一個特殊的類,它的特殊之處在於只能被繼承,不能被實例化 抽象類是一個介於類和接口直接的一個概念, 同時具有類和接口的部分特性,能夠用來實現歸一化設計 import abc #利用abc模塊實現抽象類 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定義抽象方法,無需實現功能 def read(self): '子類必須定義讀功能' pass3. 屬性查找(*****) 在沒有出現菱形繼承的狀況下,屬性的查找是按照從左往右的順序一個分支一個分支的找下去 在單繼承背景下,不管是新式類仍是經典類屬性查找順序都同樣 先obj->類->父類->... 在出現菱形繼承(一個子類繼承的多個分支最終匯聚到一個非object類)的狀況下, 在多繼承背景下,若是一個子類繼承了多個分支,可是多個分支最終匯聚到一個非object類(菱形繼承問題) 面試常問問題***** (新式類 繼承object類的纔是新式類 廣度優先) (經典類 若是你直接建立一個類在2.7中就是經典類 深度優先) 新式類:廣度優先查找,按照從左往右的順序一個分支一個分支的找下去,在最後一個分支纔去查找頂級類 obj->A->B->E->C->F->D->G->object 經典類(沒有object類):深度優先查找,按照從左往右的順序一個分支一個分支的找下去,在第一個分支就查找頂級類 obj->A->B->E->G->C->F->D (.mro()參考該對象所屬類的mro查找) 類有兩種屬性:數據屬性和函數屬性 1. 類的數據屬性是全部對象共享的 2. 類的函數屬性是綁定給對象用的 在obj.name會先從obj本身的名稱空間裏找name, 找不到則去類中找,類也找不到就找父類... 最後都找不到就拋出異常4. 派生(*****) 在子類中定義本身的屬性,若是與父類的屬性重名,那以本身的爲準. 在子類派生的新方法中重用父類的功能: 方式一:指名道姓地調用某一個類的函數 特色:類名.函數名(對象,參數1,參數2,...)==> 1. 與繼承無關 2. 沒有自動傳值的效果 class OldboyPerson:#父類 school="oldboy" def __init__(self,name,age,gender): self.name=name self.age=age self.gender=gender class Teacher(OldboyPerson):#子類 def __init__(self,name,age,gender,level,salary): OldboyPerson.__init__(self,name,age,gender) # super(Teacher, self).__init__(name, age, gender) self.level = level self.salary = salary 方式二:super()獲得一個特殊的對象,該對象專門用來引用父類的屬性 特色:super(本身的類名, self).父類的方法(參數1,參數2,...) == > super().父類的方法(參數1,參數2,...) 1. 嚴格依賴繼承,super會徹底參照類的mro列表去便歷父類中屬性依次查找 2. 有自動傳值的效果 固然子類也能夠添加本身新的屬性或者在本身這裏從新定義這些屬性 (不會影響到父類),須要注意的是,一旦從新定義了本身的屬性且與父類重名, 那麼調用新增的屬性時,就以本身爲準了。 class Riven(Hero): camp='Noxus' def attack(self,enemy): #在本身這裏定義新的attack,再也不使用父類的attack,且不會影響父類 print('from riven') def fly(self): #在本身這裏定義新的 print('%s is flying' %self.nickname) 在子類中,新建的重名的函數屬性,在編輯函數內功能的時候, 有可能須要重用父類中重名的那個函數功能,應該是用調用普通函數的方式, 即:類名.func(),此時就與調用普通函數無異了, 所以即使是self參數也要爲其傳值 class Riven(Hero): camp='Noxus' def __init__(self,nickname,aggressivity,life_value,skin): Hero.__init__(self,nickname,aggressivity,life_value) #調用父類功能 self.skin=skin #新屬性 def attack(self,enemy): #在本身這裏定義新的attack,再也不使用父類的attack,且不會影響父類 Hero.attack(self,enemy) #調用功能 print('from riven') def fly(self): #在本身這裏定義新的 print('%s is flying' %self.nickname) r1=Riven('銳雯雯',57,200,'比基尼') r1.fly() print(r1.skin) ''' 運行結果 銳雯雯 is flying 比基尼 '''