文章目錄
- 一、什麼是繼承?
- 二、繼承定義格式
- 三、檢視繼承關系
- 四、繼承重寫
- 五、多繼承
一、什麼是繼承?
繼承
是一種類間關系, 描述一個類從另一個類擷取成員資訊的類間關系。
如果一個類别A“繼承自”另一個類别B,就把這個A稱為“B的子類别”,而把B稱為“A的父類别”也可以稱“B是A的超類”。
繼承必定發生在兩個類之間, 參與繼承關系的雙方成為是
和
父類
子類
。
父類提供成員資訊, 子類擷取成員資訊。
繼承可以使得子類具有父類的各種屬性和方法,而不需要再次編寫相同的代碼。在令子類繼承父類的同時,可以重新定義某些屬性,并重寫某些方法,即覆寫父類别的原有屬性和方法,使其獲得與父類不同的功能。另外,還可以為子類追加新的屬性和方法。
二、繼承定義格式
定義格式:
calss 類名(父類名):
pass
繼承父類的成員:包括變量和方法
注:
子類可以添加父類沒有的成員
父類私有成員不可被繼承
那麼接下來用一個例子來看一下繼承:
class Father:
def __init__(self):
self.name = None
self.place = None
self.__id_card = None # 對成員變量進行私有設定:self.__變量名 = 值
def hello(self):
print("hello,武漢加油,我是%s" % self.name)
# 子類
class Son(Father):
def sing(self): # # 為子類追加新的方法
print("會唱歌")
son1 = Son()
son1.name = "小明" # 子類擁有父類的name屬性
son1.hello() # 子類調用父類方法
son1.sing() # 子類調用自己的方法
#son1.__id_card # AttributeError: 'Son' object has no attribute '__id_card'
# 會報錯,因為父類私有成員不可被繼承
程式運作結果:
三、檢視繼承關系
類名.__mro__可以檢視繼承關系
如以上示例代碼最後加上一行:print(Son.mro)
列印結果:
再寫個簡單示例說明一下:
ass Father(object):
pass
class Son(Father):
pass
class Sun(Son):
pass
print(Sun.__mro__)
sun1 = Sun()
執行結果:
一句話,左邊的繼承右邊的,即Sun —>Son ----->Father---->object
越往右資格越老。是以,在python3 中 object類是所有類的父類。
四、繼承重寫
程式執行個體:
lass Father:
def play(self):
print("釣魚")
class Son(Father):
def play(self): # 重寫 (覆寫)
print("打遊戲")
son1 = Son()
son1.play()
print(son1)
執行結果:
那麼,如何在子類裡調用父類的方法呢?接着以上程式往下看:
class Father:
def play(self):
print("釣魚")
class Son(Father):
def play(self): # 重寫 (覆寫)
print("打遊戲")
# 調用格式一:
# 父類名.方法名(對象)
Father.play(self)
# 調用格式二:
# super(子類名,對象).方法名()
super(Son,self).play()
# 調用格式三: 常用這個
# super().方法名()
super().play()
son1 = Son()
son1.play()
執行結果:
五、多繼承
多繼承也好了解,類似于一個女兒繼承了媽媽的美麗和父親的聰明,即一個子類繼承了兩個或以上父類的成員就叫多繼承。
程式示例:
class Father1:
def sing(self):
print("唱歌唱得好聽")
class Father2:
def dance(self):
print("跳舞跳得好")
class Son(Father2,Father1):
pass
son1 = Son()
son1.sing()# 子類對象可以調用兩個父類的成員(成員變量和成員方法)
son1.dance()
執行結果:
多繼承⽤起來簡單. 也很好了解. 但是多繼承中, 存在着這樣⼀個問題. 當兩個⽗類中出現了重名⽅法的時候. 這時該怎麼辦呢? 這時就涉及到如何查找⽗類⽅法的這麼⼀個問題.即MRO(method resolution order) 問題. 在python中這是⼀個很複雜的問題. 因為在不同的python版本中使⽤的是不同的算法來完成MRO的.
這裡需要補充一下python中類的種類:
在python2x版本中存在兩種類.:
⼀個叫經典類. 在python2.2之前. ⼀直使⽤的是經典類. 經典類在基類的根如果什麼都不寫.
⼀個叫新式類. 在python2.2之後出現了新式類. 新式類的特點是基類的根是object類。
python3x版本中隻有一種類:
python3中使⽤的都是新式類. 如果基類誰都不繼承. 那這個類會預設繼承 object
我們使用的python3沒必要研究python2了(python2今年即2020年就不維護了),MRO啥的在這裡先不談,我們現在的目标是知道怎麼用的就行了,回歸正題,當遇到兩個⽗類中出現了重名⽅法的時候.,記住
子類繼承的方法是排在最前面的那個父類的方法
,下面看一下程式示例:
class Father1:
def sing(self):
print("唱歌唱得好聽")
def play(self):
print("釣釣魚")
class Father2:
def dance(self):
print("跳舞跳得好")
def play(self):
print("打打球")
# 多個父類成員沖突的情況
class Son(Father2,Father1):# Father2在前,則父類成員沖突時會優先繼承Father2的play方法
pass
son1 = Son()
son1.play()# 打打球
print(Son.__mro__)
執行結果:
那麼,隻能根據位置指定繼承方法嗎?有沒有一種方法可以指定繼承自哪個父類而不受繼承的父類參數位置影響?當然可以,下面嘗試給出以下代碼:
class Father1:
def sing(self):
print("唱歌唱得好聽")
def play(self):
print("釣釣魚")
class Father2:
def dance(self):
print("跳舞跳得好")
def play(self):
print("打打球")
# 多個父類成員沖突的情況
class Son(Father2,Father1):
def play(self):
Father1.play(self)
son1 = Son()
# son1.
son1.play()
print(Son.__mro__)
執行結果:
可以看出,以上代碼隻是在子類中重新定義了該方法并在該方法中調用需要指定的父類方法。