目錄python
在 python 中,一個子類能夠繼承多個父類,其餘語言只能一個子類繼承一個父類。編程
目的:減小代碼冗餘(減小重複代碼)編程語言
先肯定誰是子類,誰是父類函數
在定義類時,子類 + (),括號內填父類的名字,實現繼承設計
使用 __bases__
方法,能夠獲取當前類所繼承的類3d
class Father1: pass class Father2: pass class Son1(Father1): pass class Son2(Father1, Father2): pass print(Son1.__bases__) # 查看父類 print(Son2.__bases__)
運行結果:code
(<class '__main__.Father1'>,) (<class '__main__.Father1'>, <class '__main__.Father2'>) Process finished with exit code 0
繼承描述的是子類與父類之間的關係,是一種什麼是什麼的關係。要找出這種關係,必須先抽象再繼承,抽象即抽取相似或者說比較像的部分。對象
抽象分紅兩個層次:blog
抽象最主要的做用是劃分類別(能夠隔離關注點,下降複雜度),以下圖所示:繼承
繼承:基於抽象的結果,經過編程語言去實現它,確定是先經歷抽象這個過程,才能經過繼承的方式去表達出抽象的結構。
抽象只是分析和設計的過程當中,一個動做或者說一種技巧,經過抽象能夠獲得類,以下圖所示:
在繼承背景下,對象屬性的查找順序:
注意:對象查找屬性,若子類有,無論父類有沒有,以子類的爲準。
class Foo: def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') self.f1() class Bar(Foo): def f1(self): print('Bar.f1') # 對象查找屬性的順序:對象本身-》對象的類-》父類-》父類。。。 obj = Bar() # self是obj自己,即找到Bar的f1() obj.f2()
運行結果:
Foo.f2 Bar.f1 Process finished with exit code 0
子類中新定義的屬性的這個過程叫作派生,而且須要記住子類在使用派生的屬性時始終以本身的爲準。
指名道姓訪問某一個類的函數:該方式與繼承無關
# 直接經過 父類.(調用)__init__,把__init__當作普通函數使用,傳入對象與繼承的屬性. class Father: def __init__(self, name, age): self.name = name self.age = age class Son(Father): def __init__(self, name, age, weight, height): Father.__init__(self, name, age) self.weight = weight self.height = height
super()
方法super()
會獲得一個特殊的對象,該對象就是專門用來訪問父類中的屬性的(按照繼承的關係)super().__init__
(不用爲self傳值)super()
的完整用法是 super(本身的類名,self)
,在python2中須要寫完整,而python3中能夠簡寫爲 super()
class Father: def __init__(self, name, age): self.name = name self.age = age class Son(Father): def __init__(self, name, age, weight, height): super().__init__(name, age) self.weight = weight self.height = height
在 python2 中,纔有纔會有新式類與經典類之分;在 python3 中,全部的類都是新式類。
繼承 object 的類都稱之爲新式類。
在 python3 中,若是子類沒有繼承自定義的類,都默認繼承 object 。
class Foo(): pass class Goo(Foo): pass print(Foo.__bases__) print(Goo.__bases__)
運行結果:
(<class 'object'>,) # 默認繼承 object (<class '__main__.Foo'>,) Process finished with exit code 0
在 python2 中,凡是沒有繼承 object 的類都是經典類。
在Java和C#中子類只能繼承一個父類,而Python中子類能夠同時繼承多個父類,如A(B,C,D)
若是繼承關係爲非菱形結構,則會按照先找B這一條分支,而後再找C這一條分支,最後找D這一條分支的順序直到找到咱們想要的屬性
若是繼承關係爲菱形結構,即子類的父類最後繼承了同一個類,那麼屬性的查找方式有兩種:
經典類:一條路走到黑,深度優先
新式類:不找多各種最後繼承的同一個類,直接去找下一個父類,廣度優先
可使用下面的代碼逐一進行驗證:
# 驗證 class A: def test(self): print('from A') pass class B(A): def test(self): print('from B') pass class C(A): def test(self): print('from C') pass class D(B): def test(self): print('from D') pass class E(C): def test(self): print('from E') pass class F(D, E): def test(self): print('from F') pass f1 = F() f1.test()
結果:
# 新式類: F-D-B-E-C-A-object # 經典類: F-D-B-A-E-C
mro()
方法對於多繼承的類,python 提供了 mro()
方法,便捷的查看繼承的查找順序。
對於上述代碼,咱們可使用 mro()
方法:
# print(F.mro()) # 新式類下: for i in F.mro(): print(i)
運行結果:
<class '__main__.F'> <class '__main__.D'> <class '__main__.B'> <class '__main__.E'> <class '__main__.C'> <class '__main__.A'> <class 'object'> Process finished with exit code 0