1,複習1python
# 面向對象編程 # 思想:角色的抽象,建立類,建立角色(實例化),操做這些示例 # 面向對象的關鍵字 class 類名: 靜態屬性 = 'aaa' def __init__(self):pass 類名.靜態屬性 # --儲存在類的命名空間裏 對象 = 類名() # 實例化:創造了一個self對象,執行init方法,返回self對象給外部 # 對象.屬性 # 對象.方法 綁定方法,方法和對象綁定到了一塊兒 # 類名.方法(對象) # 對象可使用靜態變量?True # 類可使用對象裏的屬性嗎?False
2,複習2面試
# 組合 # 一個類的對象是另一個類的屬性 # 什麼有什麼的關係 class A: def __init__(self): self.name = 'egon' class B: def __init__(self,year,month,day): self.year = year self.month = month self.day = day b = B(18,1,17) a = A() a.birth = b print(b.year) # 18 print(a.birth.year) # 18
3,面向對象的三大特性:繼承,多態和封裝,很是很是重要的,計算機領域的三大特性算法
什麼是繼承:繼承是一種建立新類的方式,在Python中,新建的類能夠繼承一個或多個父類,父類又可稱爲基類或超類,新建的類稱爲派生類或子類編程
class A:pass # 父類,基類,超類 class B:pass # 父類,基類,超類 class A_son(A,B):pass # 子類,派生類 class AB_son(A):pass # 子類,派生類 # 一個類 能夠被多個類繼承 # 一個類 能夠繼承多個父類 ----這個只有Python裏面纔有 print(A_son.__bases__) # (<class '__main__.A'>, <class '__main__.B'>) print(AB_son.__bases__) # (<class '__main__.A'>,) print(A.__bases__) # (<class 'object'>,)
4,類裏面,剛開始加載類的時候,就從上到下把類裏面的名字加載進去了,加載進去後才能夠用類名.靜態屬性。佔內存的也只是裏面的變量名字而已設計模式
5,object在類食物鏈的頂端, python3裏面沒有繼承父類,默認繼承object,這種累叫作新式類,object類是一個很是強大的類,裏面實現了不少不少的內容,object裏面有不少雙下方法網絡
6,一般的繼承都是咱們本身寫的類,可是到網絡編程的時候,咱們會接觸到繼承Python裏面已經存在的類,例如str等python2.7
7,抽象,抽取相似或者比較像的部分,抽象最主要的做用是劃分類別,能夠隔離關注點,下降複雜度spa
8,類和類的關係叫作繼承,類和對象的關係叫作實例化。設計
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def bite(self,person): person.hp -= self.aggr class Person(Animal): pass jin = Dog('bossjin',200,500) # 子類沒有__init__方法,會去調用父類的雙下init方法 print(jin.name)
9,子類和父類都有的方法,會優先調用誰的呢?這是一道面試題,傳誰的self就運行誰的方法。code
class Animal: def __init__(self): print("執行Animal.__init__") self.func() def eat(self): print('%s eating'%self.name) def drinking(self): print("%s dringking"%self.name) def func(self): print("Animal.func") class Dog(Animal): def guard(self): print('guarding') def func(self): print('Dog.func') dog = Dog() # 這兒調用的是Dog類裏面的func.由於self傳得是dog
運行結果:
執行Animal.__init__
Dog.func
10,對於下面的問題怎麼解決呢?
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def __init__(self,name,aggr,hp,kind): self.kind = kind def bite(self,person): person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') print(jin.name) # AttributeError: 'Dog' object has no attribute 'name' # 錯誤緣由,本身有了init就不會再去運行父類的init方法,
11,派生屬性
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp class Dog(Animal): def __init__(self,name,aggr,hp,kind): Animal.__init__(self,name,aggr,hp) # 這個地方咱們不只完成了繼承,還完成了派生,也就是一個派生屬性,新添加的屬性 self.kind = kind def bite(self,person): person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') print(jin.name) # bossjin
12,除了有派生屬性,還有派生方法,父類沒有子類有的就是派生方法;父類中沒有的屬性,在子類中出現,叫作派生屬性;父類中沒有的方法,在子類中出現,叫作派生方法。
只要是子類的對象調用,子類中有的名字,必定用子類的,子類中沒有才找父類的,若是父類也沒有,報錯;若是父類子類都有,用子類的;若是還想用父類的,單獨調用父類的,須要本身傳self參數。
13,既想實現新的功能,也想用父類的功能,須要單獨調用父類的
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def eat(self): print("吃藥回血") self.hp += 100 class Dog(Animal): def __init__(self,name,aggr,hp,kind): Animal.__init__(self,name,aggr,hp) # 這個地方咱們不只完成了繼承,還完成了派生,也就是一個派生屬性,新添加的屬性 self.kind = kind # 派生屬性 def eat(self): Animal.eat(self) # 若是既想實現新的功能也想使用父類本來的功能,還須要在子類中再調用父類 self.teeth = 2 def bite(self,person): # 派生方法 person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') jin.eat() print(jin.teeth)
14,另一個調用父類方法的Python3中的用法,super,類內和類外均可以用,內部能夠不傳參,外部必傳
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def eat(self): print("吃藥回血") self.hp += 100 class Dog(Animal): def __init__(self,name,aggr,hp,kind): super().__init__(name,aggr,hp) # self 不須要單獨傳了,super()意思是找個人父類,而後就能夠調用父類的init了 # 這個地方省略了兩個參數 Dog類和self對象兩個參數 # super關鍵字只要新式類中有,不是Python3,Python中全部的類都是新式類,Python2中兩種類共存 # super還能夠再類外面用 self.kind = kind def eat(self): Animal.eat(self) self.teeth = 2 print('son class') def bite(self,person): person.hp -= self.aggr jin = Dog('bossjin',200,500,'teddy') jin.eat() print(jin.teeth) super(Dog,jin).eat() # 這兒調用的是父類的eat方法。
15,子類中調用父類方法兩種:父類名.方法名 須要本身傳self參數,super().方法名 類內不須要本身傳self
16,正常的代碼中 單繼承 ==減小了代碼的重複,繼承表達了一種子類是父類的關係,提到組合和繼承必定是兩個類以上的,看是「是」的關係仍是「有」的關係。例如:老師有生日,狗是動物
17,工做中用的通常都是單繼承,多繼承通常就是設計模式,或者面試中用到,多繼承的繼承順序問題
class A: def func(self):print('A') class B: def func(self):print('B') class C: def func(self): print('C') class D(A,B,C): def func(self): print('D') # 調用順序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
18,鑽石繼承問題:
class A: def func(self):print('A') class B(A): def func(self):print('B') class C(A): def func(self): print('C') class D(B,C): def func(self): print('D') # 調用順序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
19,Python3裏面全部的新式類都是採用廣度優先的方式,漏斗,若是後面有機會找到爺爺類,那麼就能夠廣度優先找
# 漏斗 class A: def func(self):print('A') class B(A): def func(self):print('B') class E: def func(self):print('E') class C(E): def func(self): print('C') class D(B,C): def func(self): print('D') # 調用順序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>]
20,小烏龜問題,就是一個六邊形,
# 小烏龜 class F: def func(self):print('F') class A(F): def func(self):print('A') class B(A): def func(self):print('B') class E(F): def func(self):print('E') class C(E): def func(self): print('C') class D(B,C): def func(self): print('D') # 調用順序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>]
21,get 一個算法,method resolution order mro,新式類,廣度優先;經典類是深度優先(一條道走到黑,只要能到就一直走這條道,走到頭就走另一條),繼承object的類纔是新式類,經典類若是直接建立一個類在2.7中就是經典類,深度優先。
22,多繼承中,咱們子類的對象調用一個方法,默認是就近原則,經典類中,深度優先,新式類中,廣度優先,python2.7新式類和經典類共存,新式類要繼承object,python3中只有新式類,默認繼承object,經典類和新式類有一個區別super,mro方法只在新式類中存在
23,super的本質,單繼承裏面永遠是父類,只有多繼承纔會出現同級的super。
class A: def func(self):print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() print('D') d = D() d.func() print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] # A # C # B # D # super的本質,不是直接找父類,而是根據調用者的節點位置的廣度優先順序來的