面向對象的三大特性————繼承,多態
1,繼承:繼承是一種創建新類的方式,在python中,新建的類可以繼承一個或多個父類,父類又可稱為基類或超類,新建的類稱派生類或子類。
一個類可以被多個類繼承,一個類可以繼承多個父類。
沒有繼承父類默認繼承object-----新式類,python3中都是新式類,object是所有python類的父類。
1.1單繼承
class A():pass #父類 class B():pass #父類 class Ab(A):pass #單繼承 class C(A,B):pass #多繼承
查看繼承
class A():pass class Av(object):passclass B():pass class Ab(A,B):pass print(Ab.__bases__) print(A.__bases__) print(Av.__bases__) #(<class ‘__main__.A‘>, <class ‘__main__.B‘>) #(<class ‘object‘>,) #(<class ‘object‘>,)
抽象與繼承,抽象即抽取類似或者說比較像的部分。
繼承:是基於抽象的結果,通過編程語言去實現它,先抽象,再用繼承的方式去表達出抽象的結構。
class Animal:View Codedef __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) super().eat() # 如果既想實現新的功能也想使用父類原本的功能,還需要在子類中再調用父類 self.teeth = 2 def bite(self,person): # 派生方法 person.hp -= self.aggr jin = Dog(‘金老板‘,100,500,‘吉娃娃‘) jin.eat() print(jin.hp) class Person(Animal): def __init__(self,name,aggr,hp,sex): Animal.__init__(self,name,aggr,hp) self.sex = sex # 派生屬性 self.money = 0 # 派生屬性 def attack(self,dog): dog.hp -= self.aggr def get_weapon(self,weapon): if self.money >= weapon.price: self.money -= weapon.price self.weapon = weapon self.aggr += weapon.aggr else: print("余額不足,請先充值") alex = Person(‘alex‘,1,2,None) alex.eat() print(alex.hp) jin.bite(alex) print(alex.hp)
在子類中,新建的重名的函數屬性,在編輯函數內功能的時候,有可能需要父類中重命名的那個函數功能,應該使用調用普通函數的方式,即:類名.func(),在python3中,子類執行父類的方法可以直接用supre.func()方法。
class A: def hahaha(self): print(‘A‘) class B(A): def hahaha(self): super().hahaha() #super(B,self).hahaha() #A.hahaha(self) print(‘B‘) a = A() b = B() b.hahaha() super(B,b).hahaha()View Code
父類中沒有的屬性,在子類中出現叫做派生屬性;父類中沒有的方法在子類中出現叫派生方法。
只要是子類的對象調用,子類中有的名字一定用子類,子類沒有的才找父類。如果子類父類都有的,用子類的,用父類的,需要調用父類的:父類名.方法名,需要自己傳self,super().方法名,不需要傳self。
2,多繼承
mro方法,查看繼承順序
新式類中的繼承順序:廣度優先
# class A(object): # 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‘) # # b = D() # b.func() # print(B.mro()) #A,C,B,DView Code
經典類中深度優先(沒有mro方法)
super的本質:不只是單純的找父類而是根據調用者的節點位置的廣度優先順序來的。
3,接口類與抽象類
3.1接口類:python原生不支持的
規範格式:模塊abc模塊
# from abc import abstractclassmethod,ABCMeta # class Animal(metaclass=ABCMeta): # @abstractclassmethod # def pay(self,money): # pass # class Wecchat(Animal): # def pay(self,money): # print("已用微信支付了%s元"%money) # # class Alipay(Animal): # def pay(self,money): # print("已用支付寶支付了%s元"%money) # class Applepay(Animal): # def pay(self,money): # print("已用App支付了%s元"%money) # def pay(pay_obj,moeny): # pay_obj(moeny) # # # wechat=Wecchat() # ali=Alipay() # app=Applepay() # wechat.pay(23) # ali.pay(54) # app.pay(23)View Code
3.2抽象類
類是從一堆對象中抽取相同的內容而來,那麽抽象類就是從一堆類中抽取相同的內容而來的。
抽象類:規範
一般情況下單繼承能實現的功能都是一樣的,所以在父類中可以有一些簡單的基礎實現,多繼承的情況由於功能比較復雜,所以不容易抽象出相同的功能的具體實現寫在父類中。
#一切皆文件 import abc #利用abc模塊實現抽象類 class All_file(metaclass=abc.ABCMeta): all_type=‘file‘ @abc.abstractmethod #定義抽象方法,無需實現功能 def read(self): ‘子類必須定義讀功能‘ with open(‘filaname‘) as f: pass @abc.abstractmethod #定義抽象方法,無需實現功能 def write(self): ‘子類必須定義寫功能‘ pass class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print(‘文本數據的讀取方法‘) def write(self): print(‘文本數據的讀取方法‘) class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print(‘硬盤數據的讀取方法‘) def write(self): print(‘硬盤數據的讀取方法‘) class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print(‘進程數據的讀取方法‘) def write(self): print(‘進程數據的讀取方法‘) wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #這樣大家都是被歸一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)View Code
抽象類和接口類:面向對象開發規範所有的接口類和抽象類都不能實例化。
# python # python中沒有接口類 : # python中自帶多繼承 所以我們直接用class來實現了接口類 # python中支持抽象類 : 一般情況下 單繼承 不能實例化 # 且可以實現python代碼
接口類與抽象類的總結:
pyhton中沒有接口類,有抽象類,abc模塊中metaclass=ABCMeta,@abstructmethod
本質是用來做代碼規範的,希望在子類中實現和父類方法名字完全一樣的方法。
抽象類與接口類的區別:
在java的角度上看是有區別的,java本來就支持單繼承,所以有了抽象類;但java沒有多繼承,所以為了接口隔離原則,設計了接口這個概念,支持了多繼承。
python中既支持單繼承也支持多繼承,所以對於接口類和抽象類的區別就不太明顯,甚至在python中沒有內置接口類。
二,多態
Python天生支持多態,多態指的是一類事物有多種形態
多態性是指在不考慮實例類型的情況下使用實例
鴨子類型:不依賴父類的情況下實現兩個相似的類中的同名方法。
序列類型有多種形態:字符串,列表,元組,但它們沒有直接的繼承關系
# list tuple # 不崇尚根據繼承所得來的相似 # 只是自己實現我自己的代碼就可以了。 # 如果兩個類剛好相似,並不產生父類的子類的兄弟關系,而是鴨子類型 # list tuple 這種相似,是自己寫代碼的時候約束的,而不是通過父類約束的 # 優點 : 松耦合 每個相似的類之間都沒有影響 # 缺點 : 太隨意了,只能靠自覺 # class List(): # def __len__(self):pass # class Tuple(): # def __len__(self):pass # # def len(obj): # return obj.__len__() # # l = Tuple() # len(l) # # # 強類型語言 多態 # # python 語言 鴨子類型
面向對象的三大特性————繼承,多態