python中super()方法的理解


python中對象方法的定義很怪異,第一個參數一般都命名為self(相當於其它語言的this),用於傳遞對象本身,

有時候還會有一個參數cls(相當於類名,當直接調用類方法的時候使用)。

python2中super()的用法:

     super(class,self).__init__()

python3中super()的用法:

     super().__init__()

 
        

 

在類的繼承里面super()非常常用, 它解決了子類調用父類方法的一些問題, 父類多次被調用時只執行一次。

def super(cls, inst):

      mro = inst.__class__.mro()

      return mro[mro.index(cls) + 1]

當使用 super(cls, inst) 時,Python 會在 inst 的類的 MRO 列表上搜索 cls 的下一個類。

而查看inst類的的MRO列表的方法就是:

類.mro()   或  類.__mro__ 或 inst.__class__.mro()

例如:當C是一個類的時候,獲得一個類的MRO的方法是

C.mro() 或  C.__mro__  或 C().__class__.mro()

 

執行過程:

  當執行生成D的inst對象的時候,先執行Enter D

這個時候D類的MRO列表為[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

當執行super(D,self) 就是在self對象的類的MRO列表中查找D的下一個父類。這個self是D類的實例對象inst。

而D類中的MRO列表中D的下一個父類是B。

例如:

1、super單繼承的時候:

 

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)

 

結果是什么呢?

 

為什么是8?

執行b.add(2)的時候,執行A中的add()函數,執行的時候這個時候的self是b這個實例,所以這個self.n是3

所以執行3+2=5

然后執行super的下一句5+3=8。

2、super多繼承的時候

 

#super的多繼承
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)

 

 這個結果是什么呢?

我認為是5+B.add+C.add+A.add+5=5+3+4+2+5=19

看下輸出的結果:

 

執行過程是什么樣的呢?

詳細的代碼分析如下:

 

class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m#第4步執行,A.add(2),這個時候self=b,n=5,即n=5+2=7
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)#第2步執行,相當於super(B,d),在d的MRO[D,B,C,A,Object]中B的下一個C.add(2),這個時候self=b,n=5
self.n += 3 #第6步執行,n=11+3=14
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
print('self is {0} @C.add'.format(self))
super().add(m)#第3步執行,相當於super(C,d),在d的MRO[D,B,C,A,Object]中C的下一個A.add(2),這個時候self=b,n=5
self.n += 4 #第5步執行,n=7+4=11
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)#第1步執行相當於super(D,d)這個時候就會返回在d的MRO[D,B,C,A,Object]中D的下一個類B,執行B.add(2)
self.n += 5 #第7步執行,n=14+5=19
d = D()
print(d.__class__.mro())#[D, B, C, A,object]
d.add(2)
print(d.n)

 當我們調用 super() 的時候,實際上是實例化了一個 super 類

在大多數情況下, super 包含了兩個非常重要的信息: 一個 MRO 以及 MRO 中的一個類。當以如下方式調用 super 時:

super(a_type, obj)

MRO 指的是 type(obj) 的 MRO, MRO 中的那個類就是 a_type , 同時 isinstance(obj, a_type) == True 。

當這樣調用時:

super(type1, type2)

MRO 指的是 type2 的 MROMRO 中的那個類就是 type1 ,同時 issubclass(type2, type1) == True 。

那么, super() 實際上做了啥呢?簡單來說就是:提供一個 MRO 以及一個 MRO 中的類 C , super() 將返回一個從 MRO 中 C 之后的類中查找方法的對象。

也就是說,查找方式時不是像常規方法一樣從所有的 MRO 類中查找

舉個例子, 有個 MRO:

[A, B, C, D, E, object]

下面的調用:

super(C, A).add()

super 只會從 C 之后查找,即: 只會在 D 或 E 或 object 中查找 add 方法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM