上篇文章分析了類的組合,那么什么時候用繼承,什么時候用組合?
用組合:當類之間有顯著不同,并且較小的類是較大的類所需要的組件時
用繼承:當類之間有很多相同的功能時,可提取這些相同的功能組成基類來繼承
子類繼承了父類的所有屬性,但子類中可以定義與父類中同名的屬性,調用時優先使用子類自己定義的屬性而不是繼承來
的屬性,不會對父類的屬性有影響。
class Dad:money= 10def __init__(self,name):print('I am father')self.name= namedef hit_son(self):print('%s 正在打兒子' %self.name)class Son(Dad): #Son繼承了Dadpassprint(Dad.__dict__)
print(Son.__dict__) #子類的屬性字典里沒有父類的屬性卻可以調用到
print(Son.money) #因為Son繼承了Dad所以就有了Dad的那筆錢(數據屬性)#print(Son.hit_son()) #也繼承了函數屬性,但不能直接用
#實例化之后就可以用了
v = Son('白胡子')
v.hit_son()
print(v.__dict__) #同樣,實例中也沒有父類的屬性字典,但是可以調用
自學python需要的軟件?運行結果:
類的繼承分為兩種。一種叫派生,一種叫接口繼承
派生: 子類在繼承了之后又定義了新的屬性和動作(最好不與父類重名),但派生并不好用,會使代碼的耦合性變大,獨立性降低,不利于執行
接口繼承: 父類中規定好了子類需要實現的方法,但不在父類里面實現,子類繼承后才實現
#定義一個基類(用于接口繼承的父類)
class All_file:def read(self):passdef write(self):pass#繼承了基類后,在子類實現read和write的具體方法
#而父類只定義了一個接口,沒有實現具體的方法
class Disk(All_file): def read(self):print("disk read")def write(self):print('disk write')class Cdrom(All_file):def read(self):print("cdrom read")def write(self):print('cdrom write')#不定義write方法
class Mem(All_file):def read(self):print('mem read')v1 = Mem()
v1.read()
v1.write() #但卻可以調用write方法,此時調用的就是父類的方法,沒有內容用接口模塊abc來實現
import abc #導入abc模塊#定義一個基類(用于接口繼承的父類)
class All_file(metaclass=abc.ABCMeta): #必要參數@abc.abstractmethoddef read(self):pass@abc.abstractmethoddef write(self):pass#不定義write方法就無法實例化,被嚴格限制了要使用父類中定義的方法
class Mem(All_file):def read(self):print('mem read')'''def write(self):pass'''v1 = Mem()
v1.read()
v1.write()
運行結果:
import abc #導入abc模塊#定義一個基類(用于接口繼承的父類)
class All_file(metaclass=abc.ABCMeta): #必要參數@abc.abstractmethoddef read(self):pass@abc.abstractmethoddef write(self):pass#不定義write方法就無法實例化,被嚴格限制了要使用父類中定義的方法
class Mem(All_file):def read(self):print('mem read')'''def write(self):pass'''v1 = Mem()
v1.read()
v1.write()
python筆記總結?運行結果:
規范子類,即嚴格控制子類需要基類的那些的功能,才去繼承基類(提取出來的父類)
(子類優先于父類查找、深度優先、廣度優先原則)
class A:passclass B(A):passclass C(A):passclass D(C):passclass E(B,D):passv = E() #實例化E類
print(E.__mro__) #查看E類的繼承順序(里面遵循了深度優先和廣度優先原則)
運行結果:
class Teacher:City= '東京'def __init__(self,name,salary,subject,age):self.name= nameself.salary= salaryself.subject= subjectself.age= agedef teach_course(self):print('{}老師正在教{}課'.format(self.name,self.subject))class Student(Teacher): #繼承Teacher類def __init__(self,name,salary,subject,age,heigh): #繼承的方法中又多傳入一個參數#在父類名調用父類的方法'''Teacher.__init__(self,name,salary,subject,age) #參數格式和父類的init一樣self.heigh= heigh #使新傳入的參數也變成self屬性'''#用super()來調用父類的方法super().__init__(name,salary,subject,age)#用super調用參數不需要self,而且父類名有變化仍然可以調用到self.heigh= heigh #使新傳入的參數也變成self屬性'''最直接的調用self.name= nameself.salary= salaryself.subject= subjectself.age= ageself.heigh= heigh #使新傳入的參數也變成self屬性'''#定義一個派生的方法def show_info(self): #打印信息的一個方法Teacher.teach_course(self) #調用父類中的方法,參數為self(父類中的self)print('{}的{}學生正在上{}課'.format(self.heigh,self.name,self.subject))#實例化,繼承父類就按照父類的參數去傳參數
st1 = Student('Zoro',2000,'英語',28,'2米以下')
st1.show_info()
print(st1.__class__) #查看對象所在的類
運行結果:
python子類繼承父類屬性、多態的概念:
多態的概念指出了對象如何通過它們共同的屬性和動作來操作及訪問,而不需要考慮生成它們的類;
多態反映的一種執行時的狀態,說白了就是多個子類繼承一個父類然后去調用父類的同一個方法;
幾乎只要是繼承,就會用到多態,所以不需要太糾結多態的概念,把繼承學好就夠了
#下面用一個水、冰、蒸汽三種H20狀態來闡述多態
class H2o:def __init__(self,name,temperature): #兩個參數,名字和溫度self.name= nameself.temperature= temperaturedef turn_ice(self): #變成冰if self.temperature < 0: #如果溫度小于0變成冰態print('【%s】的溫度太低,所以變成冰態!' %self.name)elif self.temperature > 0 and self.temperature < 100: #溫度大于0小于100是水態print('【%s】 液化成水態' %self.name)elif self.temperature > 100: #溫度大于100成水蒸氣態print('【%s】溫度高于100度,所以變成水蒸汽態'%self.name)class Water(H2o): #繼承H2o的水態passclass Ice(H2o): #繼承H2o的冰態passclass Steam(H2o): #繼承H2o的水蒸氣態pass#實例化,Water、Ice、Steam子類都繼承同一個父類,這里將三個子類實例化
w1= Water('水',33) #名字叫水,溫度33度
i1= Ice('冰',-25)
s1= Steam('蒸汽',3500)#冰、水、蒸汽繼承同一個父類,并且調用同一個方法;
#在這里,func函數就代表了turn_ice方法,因為該函數的功能就執行turn_ice
def func(obj):obj.turn_ice()#調用func函數,傳入的是三個實例化對象,然后再func中調用這三個實例化對象的turn_ice方法
func(w1)
func(i1)
func(s1)
運行結果:
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态