2016-02-10 43 views
1

請向我解釋以下內容。如果我執行此:超級()的第二個基類的訪問方法

class Base1: 
    def foo(self): 
     print('in Base1.foo') 

b1 = Base1() 
b1.foo() 


class Base2: 
    def foo(self): 
     print('in Base2.foo') 

b2 = Base2() 
b2.foo() 

class Child1(Base1, Base2): 
    def foo(self): 
     super(Child1,self).foo() 

c1 = Child1() 
c1.foo() 

class Child2(Base1, Base2): 
    def foo(self): 
     super(Base1,self).foo() 

c2 = Child2() 
c2.foo() 

我得到這個:

in Base1.foo 
in Base2.foo 
in Base1.foo 
in Base2.foo 

我理解的前三行輸出。但爲什麼我必須將第一個基類的名稱給super()才能獲得第二個基類的方法?

回答

4

您正在使用Method Resolution OrderMRO。根據稱爲C3 linearisation的系統,Python類繼承層次結構爲線性化,給定特定順序。

super()使用該順序查找該排序中的下一個屬性(包括方法)。給定一個當前的實例和一個類,它將搜索訂單中的以及給定的類。對於兩個Child*班,MRO首先列出Child*班,然後是Base1Base2。在你的最後一個例子中,你告訴super()Base1之後的下一節開始尋找該MRO,因此只有Base2.foo()有待發現。

您可以通過調用class.mro() method要求其MRO任何類:

>>> Child2.mro() 
[<class '__main__.Child2'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>] 

super()可用於方法太;那麼你可以很容易地看到當你選擇不同的出發點的探索會發生什麼:

>>> super(Child2, Child2()).foo 
<bound method Base1.foo of <__main__.Child2 object at 0x10f40ff98>> 
>>> super(Base1, Child2()).foo 
<bound method Base2.foo of <__main__.Child2 object at 0x10f40ffd0>> 
>>> super(Base2, Child2()).foo 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'super' object has no attribute 'foo' 
+0

我知道的方法解析順序的,但我不知道超()獲取「下一個」基類排隊......謝謝 – steffen