面向物件三大特性 封裝 繼承 多型
阿新 • • 發佈:2020-08-13
1 繼承
1:定義
繼承描敘的是兩個類之間的關係,一個類可以直接使用另一個類中已定義的方法和屬性; 被繼承的稱之為父類或基類,繼承父類的類稱之為子類;
1.減少程式碼重複 2.為多型提供必要的支援
3 繼承的使用
1 先抽象在繼承
# 抽取老師和學生的相同內容 形成一個新的類,作為它們的公共父類 class Person: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("hi my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) class Teacher(Person): #指定Teacher類繼承Person類 pass class Student(Person): #指定Student類繼承Person類 pass #建立兩個物件 t1 = Teacher("Jack","man",20) t1.say_hi() s1 = Student("Maria","woman",20) s1.say_hi()
當父類提供的屬性無法完全滿足子類的需求時,子類可以增加自己的屬性或非法,或者覆蓋父類已經存在的屬性,此時子類稱之為父類的派生類;
覆蓋
在子類中如果出現於父類相同的屬性名稱時,根據查詢順序,優先使用子類中的屬性,這種行為也稱為`覆蓋`
# 抽取老師和學生的相同內容 形成一個新的類,作為它們的公共父類 class Person: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) class Teacher(Person): #指定Teacher類繼承Person類 # Teacher類從Person類中繼承到了say_hi方法 但是,老師打招呼時應當說出自己的職業是老師,所以需要 # 定義自己的不同的實現方式 def say_hi(self): print("hi i am a Teacher") #print("my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) #上一行程式碼與父類中完全相同,可以直接呼叫父類提供的方法 Person.say_hi(self) # 建立Teacher物件 t1 = Teacher("Jack","man",20) t1.say_hi() #輸出 hi i am a Teacher # my name is Jack age is 20 gender is man
在子類中有兩種方式可以重用父類中的程式碼
1.使用類名直接呼叫 ,該方式與繼承沒有關係,即時沒有繼承關係,也可以呼叫
2.使用super()
class Vehicle: #定義交通工具類 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('開動啦...') class Subway(Vehicle): #地鐵 def __init__(self,name,speed,load,power,line): #super(Subway,self) 就相當於例項本身 在python3中super()等同於super(Subway,self) super().__init__(name,speed,load,power) self.line=line def run(self): print('地鐵%s號線歡迎您' %self.line) super(Subway,self).run() class Mobike(Vehicle):#摩拜單車 pass line13=Subway('中國地鐵','180m/s','1000人/箱','電',13) line13.run() ''' 地鐵13號線歡迎您 開動啦... '''
4 經典類與新式類
那什麼是經典類,什麼是新式類呢?
# Author:Zhang Zhao class A(object): def __init__(self): print('A') class B(A): pass # def __init__(self): # print('B') class C(A): def __init__(self): print('C') class D(B,C): pass # def __init__(self): # print('D') r1 = D()
但是在經典類中,如果B中找不到,它會優先考慮B的父親A,而不是C。
在python3中,都是遵循廣度優先的規則,在python2.7以前,應該是遵循深度優先的的規則。兩種規則沒有優劣之分
#A沒有繼承B,但是A內super會基於C.mro()繼續往後找 class A: def test(self): super().test() class B: def test(self): print('from B') class C(A,B): pass c=C() c.test() #列印結果:from B print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
5 繼承的順序
對於你定義的每一個類,python通過一個演算法算出一個查詢順序存放在(MRO)列表中,這個MRO列表就是一個簡單的所有基類的線性順序列表,例如:
F.mro() #等同於F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]