天天看點

細探Python super()

環境

預設以Python3為例,py2,3一些差別如下:

class的定義

Python3
class A:
    def __init__(self):
        pass      
python2
class A(object):
    def __init__(self):
        pass      

super()的調用

python3
class B(A):
    def  __init__(self):
        super().__init__()
        pass      
python2
class B(A):
    def __init__(self):
        super(B,self).__init__()
        pass      

單繼承

這是我們平時見到的最多的情況,一個類繼承自另一個類。我們用一個小例子簡單說明:

class A:
    def __init__(self):
        self.n = 2

    def add(self, m):
        print('self is {0} @A.add'.format(self))
        self.n += m


class B(A):
    def __init__(self):
        self.n = 3

    def add(self, m):
        print('self is {0} @B.add'.format(self))
        super().add(m)
        self.n += 3

b=B()
b.add(2)
print(b.n)      

可以先算一下最後結果是多少,然後運作一下程式。

細探Python super()

從結果看出,計算流程為:

​B: self.n = 3 ---> A: self.n + 2 = 5 ---> B: self.n = self.n + 3 = 5 + 3 = 8​

多繼承

多繼承就比較有意思了。

class A:
    def __init__(self):
        self.n = 2

    def add(self, m):
        print('self is {0} @A.add'.format(self))
        self.n += m


class B(A):
    def __init__(self):
        self.n = 3

    def add(self, m):
        print('self is {0} @B.add'.format(self))
        super().add(m)
        self.n += 3

class C(A):
    def __init__(self):
        self.n = 4

    def add(self, m):
        print('self is {0} @C.add'.format(self))
        super().add(m)
        self.n += 4


class D(B, C):
    def __init__(self):
        self.n = 5

    def add(self, m):
        print('self is {0} @D.add'.format(self))
        super().add(m)
        self.n += 5

d=D()
d.add(2)
print(d.n)      

強烈建議自己先算一下。

程式的最終輸出為:

細探Python super()

程式執行的時候,調用到B類的時候,并沒有去調用A類,而是接着去調用C類的add方法,最後調用的A類的add方法。

我們來探究一下super究竟做了什麼。

探究super

super是一個類,我們調用super()的時候,實際上是執行個體化了一個super類。

class A: pass
s=super(A)
type(s)
#output is <class 'super'>      

大多數情況下,super包含了兩個非常重要的資訊:

  1. MRO(Method Resolution Order)清單
  2. MRO的一個類

再來看多繼承中的例子。

d=D()
d.add(2)
print(d.n)      

在python console,我們輸入​

​D.mro()​

​​,對于Python2,是​

​D.__mro__​

​,傳回資訊為:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]