2017-07-29 57 views
0

我有以下代碼:調用父類方法在多重繼承

class A: 
    pass 

class B(A): 
    def foo(self, a): 
     if a: 
      return 'B' 
     return super(B, self).foo(a) 

class C: 
    def foo(self, a): 
     return 'C' 

class D(B, C): 
    def foo(self, a): 
     return super().foo(a) 

d = D() 
print(d.foo(0)) 

當我打電話d.foo(0)基於MRO它首先調用B類的和內部的foo方法,如果條件是錯誤的,它將返回super(B, self).foo(0)但類A沒有foo的方法,我希望這樣的錯誤:

AttributeError: 'super' object has no attribute 'foo' 

,但它從C類返回'C'。爲什麼?

+1

這就是'super'的重點。想一想 - 如果是直接調用父項,那麼在語言中根本不需要'超級',你可以直接在這裏調用'A'。 – wim

回答

1

super()搜索MRO的下一個類有屬性;即A不執行它並不重要,因爲仍然考慮C

對於D的MRO是DBAC

>>> D.__mro__ 
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>) 

所以super().fooD會發現B.foo,並從B.fooA被跳過,C.foo被發現;你可以自己從交互式解釋測試:

>>> super(D, d).foo 
<bound method B.foo of <__main__.D object at 0x1079edb38>> 
>>> super(B, d).foo 
<bound method C.foo of <__main__.D object at 0x1079edb38>> 

這是屬性的搜索算法的Python實現會是什麼樣子:

def find_attribute(type_, obj, name): 
    starttype = type(obj) 
    mro = iter(starttype.__mro__) 

    # skip past the start type in the MRO 
    for tp in mro: 
     if tp == type_: 
      break 

    # Search for the attribute on the remainder of the MRO 
    for tp in mro: 
     attrs = vars(tp) 
     if name in attrs: 
      res = attrs[name] 
      # if it is a descriptor object, bind it 
      descr = getattr(type(res), '__get__', None) 
      if descr is not None: 
       res = descr(
        res, 
        None if obj is starttype else obj, 
        starttype) 
      return res 

其中type_是第一個參數super()(類該方法被定義),obj是實例(所以這裏的type(d))和name是您正在查找的屬性。