第44個練習是關於繼承。
第乙個例子講的是隱式繼承,什麼是隱式繼承呢?簡單地說,當a類中存在的特性或方法x,而b類中沒有定義,直接從a類中繼承得來,這種方式得繼承就是隱式繼承。
如下面得**ex44a.py:
class
parent
(object):
defimplicit
(self):
print("parent implicit()")
class
child
(parent):
pass
if __name__ == "__main__":
dad = parent()
son = child()
dad.implicit()
son.implicit()
在parent類中定義了乙個乙個implicit的方法,作用是列印出parent implicit()
,而在child類中,並沒有新寫任何新的方法和特性,直接繼承parent類中的所有方法和特性,這就是隱式繼承。
注意的是,該處的code中,與原文不一致的地方是加了乙個if __name__ == "__main__"
, 主要的目的是複習一下前面所學到的內容。在直接執行這段**的時候,將按照原來的形式輸出。而如果採用import模組的方式,則不會列印出任何文字。
輸出的結果是:
parent implict()
parent implict()
第二個例子是在子類中重寫父類的方法或特性。有的時候,子類中包含有和父類中同樣名字的方法或特性,但是方法或特性的細節並不一樣,採用隱式繼承就無法實現子類對該方法或特性的需求,此時就需要在子類中重寫該方法或特性。
在子類中重寫的方法或特性將覆蓋掉父類中同名的方法,這就是顯式覆蓋。
**如下ex44b.[y所示:
class
parent
(object):
defoverride
(self):
print("parent override()")
class
child
(parent):
defoverride
(self):
print("child override()")
if __name__ == "__main__":
dad = parent()
son = child()
dad.override()
son.override()
**執行的結果是:
parent override()
child override()
在parent()和child()中含有相同的方法override,此時雖然child()是parent()的子類,但是重寫的方法將覆蓋掉父類中同樣名字的方法,使子類保持有新的方法或特性。
第三點涉及到是否直接採用子類的方法或特性(顯示覆蓋)還是在執行子類的方法或特性之前,首先執行父類的方法。我猜是有的場合,不能完全忽略掉父類中的方法和特性。這個時候就用到了super()函式。
**如下面的ex44c.py中所示。
class
parent
(object):
defaltered
(self):
print("parent altered()")
class
child
(parent):
defaltered
(self):
print("child, before parent altered()")
super(child,self).altered()
print("child, after parent altered()")
if __name__ == "__main__":
dad = parent()
son = child()
dad.altered()
son.altered()
執行的結果如下:
parent altered()
child, before parent altered()
parent altered()
child, after parent altered()
第乙個parent altered()
比較好理解,這是直接呼叫父類parent(object)中的alter方法得到的。
結果第二行中的child, before parent altered()
是第二個例子中的顯示覆蓋得到的結果。
真正有意思的是結果的第三行和第四行,這兩行的結果是由super(child,self).altered()
執行得到的結果。對於顯式覆蓋,重寫的altered()
方法被直接呼叫,不用再管其繼承的父類中的資訊。而用super(child,self).alter()
,將會去訪問其父類,並返回父類中的alter()
方法。
可以想想採用這種繼承的方式,在實際程式設計的時候有什麼用處,現在mark一下,因為我也沒有合適的例子。總之,如書中所講,這種方式,可以在父類方法/特性執行後再用子類的方法/特性進行替換。
下面是三種方式組合使用的**ex44d.py.
class
parent
(object):
defoverride
(self):
print("parent override()")
defaltered
(self):
print("parent altered()")
defimplicit
(self):
print("parent implicit()")
class
child
(parent):
defoverride
(self):
print("child override()")
defaltered
(self):
print("child, before parent altered()")
super(child, self).altered()
print("child, after parent altered()")
dad = parent()
son = child()
dad.implicit()
son.implicit()
dad.override()
son.override()
dad.altered()
son.altered()
執行的結果如下:
parent implicit()
parent implicit()
parent override()
child override()
parent altered()
child, before parent altered()
parent altered()
child, after parent altered()
到了這裡,就要問一句:super()函式的意義在什麼地方?因為隱式繼承和顯式覆蓋這兩種方式可以保證對父類中方法/特性的繼承和重寫,看起來功能都是足夠了。但考慮到多重繼承的情況,實際的情況可能相當複雜,例如當某個子類繼承了多個父類,child(p1,p2,p3,…),而這些父類之間可能有相同的方法/特性,或它們之間也有繼承的關係,這樣的繼承關係就相當的複雜。在super機制裡可以保證公共父類僅被執行一次,至於執行的順序,是按照mro(method resolution order):方法解析順序 進行的。
重點標記:
-super()最常見的用法是在父類的__init__
函式中使用。通常這也是唯一可以進行這種操作的地方。
-可以直接使用別的類和模組,而非依賴於隱式繼承。
-不惜一切代價去避免多重繼承。
-需要**復用的地方,可以通過組合做成模組。
《「笨辦法」學python3》Ex 3
在python3中進行數字計算和真值判斷.與c 相同,統計我的雞 print i will now count my chickens 母雞25 30 6 30 print hens 25 30 6 公雞100 25 3 4 97 print roosters 100 25 3 4 統計我的蛋 pr...
笨辦法學python3 ex6
習題6 f 格式化 f string type of people 10 x f there are types of people.binary binary do not don t y f those who know and those who 注意 f 字串的形式,我把變數放置到 此位置 ...
《「笨辦法」學python3》附錄 Ex 0
本科非計算機專業,基本零基0礎 python3 入門。筆記會概述每個練習的核心內容,分享遇見的問題以及解決方案,歡迎各位批評指正。zed強調命令列練習,命令列鏈結程式和計算機,使程式可以控制計算機。計算機中,shell是乙個殼,是指 提供使用者使用介面的軟體 基本shell分成兩類 1.圖形介面 微...