在前面一章咱們簡單介紹了一些類的分類java
object
的類以及該類的子類, 都是新式類 (Python3中統一都是新式類)object
類, 也就是Python3中全部的類都是新式類🍔在"Python3"中 class Default: # 默認繼承"object" pass print(Default.__bases__) # (<class 'object'>,)
object
的類以及該類的子類, 都是經典類 (只有Python2中才區分新式類和經典類)object
類, 因此Python2 中才有經典類🍔在"Python2"中 class Default(object): # 新式類 pass class Animal: # 經典類 pass 🍔"Python2"中"print"語法 print Default.__bases__ # (<class 'object'>,) print Animal.__bases__ # ()
ps : 新式類與經典類的屬性查找順序是不同的python
上面說到Python支持多繼承, 但新式類與經典類的屬性查找順序是不同的算法
java語言中,它不支持多繼承,只支持繼承一個父類python2.7
python語言,支持多繼承,好比 A(B,C,D)code
非菱形結構下, 經典類與新式類的屬性查找順序是同樣的繼承
若是繼承關係爲非菱形結構,則會按照先找 B 這一條分支,而後再找 C 這一條分支,最後找 D 這一條分支的順序直到找到咱們想要的屬性utf-8
class F1: def s1(self): print('F1:s1') def s2(self): print('F1:s2') class F2(F1): # def s1(self): # print('F2:s1') def s2(self): print('F2:s2') class F4(): def s1(self): print('F4:s1') def s2(self): print('F4:s2') class F3(F2,F4): def s1(self): super().s1() # 調用父類的s1方法,到底使用了哪一個父類的s1 def s2(self): print('F3:s2') f1 = F3() f1.s1() # F1:s1
一、新式類----->廣度優先
__mro__
: 只有新式類纔有的屬性, 可查看屬性查找的順序class G(object): # def test(self): # print('from G') pass class E(G): # def test(self): # print('from E') pass class B(E): # def test(self): # print('from B') pass class F(G): # def test(self): # print('from F') pass class C(F): # def test(self): # print('from C') pass class D(G): # def test(self): # print('from D') pass class A(B, C, D): def test(self): print('from A') obj = A() obj.test() print(A.__mro__) '''查找順序 (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <type 'object'>) '''
二、經典類----->深度優先
#coding:utf-8 # python2 解釋器 class G(): pass def test(self): print('G---test') class F(G): pass # def test(self): # print('FFF---test') class E(G): pass # def test(self): # print('EEE---test') class D(G): pass # def test(self): # print('DDD---test') class B(E): pass # def test(self): # print('BBB---test') class C(F): pass # def test(self): # print('CCC---test') class A(B,C,D): pass # def test(self): # print('AAA---test') a=A() a.test() # G---test
class A1: def foo(self): print('A1_foo') class A2: def foo(self): print("A2_foo") def bar(self): print("A2_bar") class B1(A1, A2): pass class B2(A1, A2): def bar(self): print("B2_bar") class C(B1, B2): pass c = C() c.foo() # A1_foo c.bar() # B2_bar print(C.__mro__) '''輸出 (<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.B2'>, <class '__main__.A1'>, <class '__main__.A2'>, <class 'object'>) '''
c.foo()
的查找順序 : C ==> B1 ===> B2 ==> A1c.bar()
的查找順序 : C ==> B1 ==> B2#coding:utf-8 # python2.7 解釋器 class A1(): def foo(self): print 'A1_foo' class A2(): def foo(self): print "A2_foo" def bar(self): print "A2_bar" class B1(A1, A2): pass class B2(A1, A2): def bar(self): print "B2_bar" class C(B1, B2): pass c = C() c.foo() # A1_foo c.bar() # A2_bar
c.foo()
的查找順序 : C ==> B1 ===> A1c.bar()
的查找順序 : C ==> B1 ==> A1 ===> A2爲了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類爲止數學
而這個MRO列表的構造是經過一個C3線性化算法來實現的class
咱們不去深究這個算法的數學原理,它實際上就是合併全部父類的MRO列表並遵循以下三條準則 :test
__mro__
方法使用其實上面咱們已經使用了這種方法, 下面再補充一點
[類名]__mro__
: 打印屬性查找順序, 是一個元組[類名].mro()
: 打印屬性查找順序, 是一個列表🍔Python2 中 #coding:utf-8 class C(object): # 繼承object類,若是不繼承,調用 mro 方法會報錯 def run(self): print "run_C" class B(C): pass class A(B): pass a = A() a.run() # run_C print A.__mro__ # (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <type 'object'>) print A.mro() # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <type 'object'>] 🍔Python3 中 class C: # 已經自動繼承了object類 def run(self): print("run_C") class B(C): pass class A(B): pass a = A() a.run() # run_C print(A.__mro__) # (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>) print(A.mro()) # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]