在使用Python編寫面向對象的代碼時,咱們會經常使用「繼承」這種開發方式。例以下面這一段代碼:python
class Info:
def __init__(self):
pass
def calc_age(self):
print('我是父類的方法')
class PeopleInfo(Info):
def __init__(self):
super().__init__()
def calc_age(self):
print(123456)
複製代碼
若是你使用PeopleInfo
初始化一個對象,而後調用這個類的calc_age
方法,咱們來看看運行效果,以下圖所示:微信
能夠看出,父類Info
裏面的calc_age
被子類裏面的calc_age
給「覆蓋」了。函數
到目前爲止,應該都是你已經知道的東西。那麼下一個問題,請問PeopleInfo
裏面的__init__
會不會覆蓋Info
裏面的__init__
?測試
爲了確認這一點,咱們來測試一下:spa
class Info:
def __init__(self):
print('我是父類的__init__')
def calc_age(self):
print('我是父類的方法')
class PeopleInfo(Info):
def __init__(self):
super().__init__()
print('我是之類的初始化方法')
def calc_age(self):
print(123456)
複製代碼
運行效果以下圖所示:code
這裏你發現父類和子類的__init__
都被運行了。cdn
不過你可能會強行解釋爲:在子類的__init__
裏面,有一行super().__init__()
,這個地方可能子類尚未徹底覆蓋父類,因此先運行了父類的方法。等到子類的__init__
所有執行完成之後,纔會覆蓋父類。對象
固然,這種強行詭辯顯然是錯誤的,但爲了證實這裏你看到的現象和這個super().__init__()
沒有任何關係,咱們不使用__init__
,而是本身定義一個:blog
class Info:
def __init__(self):
pass
def __calc_age(self):
print('我是父類的方法')
def run_father(self):
self.__calc_age()
class PeopleInfo(Info):
def __init__(self):
super().__init__()
pass
def __calc_age(self):
print(123456)
def run_son(self):
self.__calc_age()
複製代碼
運行效果以下圖所示:繼承
從這裏能夠看出,父類和子類的__calc_age
都成功運行了。
這是由於,在Python裏面,類方法或者屬性若是以雙下劃線開頭,那麼他們就是類的私有方法,在被繼承的時候,即便子類有相同名字的以雙下劃線開頭的屬性或者方法也不會覆蓋父類。
並且這些以雙下劃線開頭的私有方法或者屬性,在類內部能夠自由被其餘方法調用,可是在實例對象裏面是不能直接調用的,以下圖所示:
那麼Python是如何實現這一點的呢?實際上Python僅僅是改了一個名字而已。咱們使用dir
函數看看實例對象kingname
裏面有哪些內容,以下圖所示:
你們請注意方框框住的內容,其中的_Info__calc_age
就是父類中的__calc_age
,而_PeopleInfo__calc_age
就是子類中的__calc_age
。Python僅僅是改了一個名字,在這種雙下劃線的私有方法或者私有屬性的前面加上了_類名
,這樣就確保了子類和父類的方法名不一致。
因此,雖然在規範上,這種雙下劃線的私有方法和私有屬性是不該該在外部訪問的
,可是若是你想強行訪問,能夠個使用這種更名之後的名字:
kingname = PeopleInfo()
kingname._PeopleInfo__calc_age() # 強行調用子類的私有方法
kingname._Info__calc_age() # 強行調用父類的私有方法
複製代碼
運行效果以下圖所示:
若是這篇文章對你有幫助,請關注個人微信公衆號: 未聞Code(ID: itskingname),第一時間獲的最新更新: