1. 程式人生 > >python類中super() 的使用

python類中super() 的使用

Python中類的初始化都是__init__(), 所以父類和子類的初始化方式都是__init__(), 但是如果子類初始化時沒有這個函式,那麼他將直接呼叫父類的__init__(); 如果子類指定了__init__(), 就會覆蓋父類的初始化函式__init__(),如果想在進行子類的初始化的同時也繼承父類的__init__(), 就需要在子類中顯示地通過super()來呼叫父類的__init__()函式。

super()在單繼承中的應用:

舉個例子:

class Animal: #定義一個父類
    def __init__(self): #父類的初始化
        self.name =
'animal' self.role = 'parent' print('I am father') class Dog(Animal): #定一個繼承Animal的子類 def __init__(self): #子類的初始化函式,此時會覆蓋父類Animal類的初始化函式 print('I am son') self.name = 'dog' #定義子類的name屬性 super(Dog,self).__init__() #在子類進行初始化時,也想繼承父類的__init__()就通過super()實現 #self.name = 'dog' #若將name屬性的定義(即第10行)放在這兒,最終輸出將是dog
animal = Animal() xbai = Dog() print(xbai.name) print(xbai.role)

輸出為:

I am father #例項化Animal類後的輸出
I am son #例項化Dog類後的輸出
I am father #例項化Dog類後的輸出
animal #由於子類初始化是在進行繼承父類初始化之前,因此super()執行後,Dog類的name屬性被父類覆蓋
parent #繼承了父類的role屬性

說明:super(Dog,self)也可以寫成super(),可以理解成super(Dog,self).__init__() == Animal.__init__(self),( super(Dog,self) == Animal ) 即其返回的是當前類的繼承順序

中(針對多繼承)Dog後的一個類(也即類Animal)

self 和 super的區別:

  • self會首先呼叫自己的方法或者屬性,當自身沒有目標屬性或方法時,再去父類中尋找;super會直接去父類中尋找目標屬性或方法。如上述程式碼中定義完第十行後,self.name的返回值為’dog’,而super().name的返回值為’animal’;
  • self時類,super是預編譯指令

super()在多繼承中的應用:

程式碼例子:

class Base(object): #定義父類
    def __init__(self):
        print('Base create')

class ChildA(Base): #子類A
    def __init__(self):
        print('Enter A')
        super(ChildA,self).__init__()
        print('Leave A')
    
class ChildB(Base):
    def __init__(self):
        print('Enter B')
        super(ChildB,self).__init__()
        self.name = 'B'
        print('Leave B')

class ChildC(ChildA,ChildB):#在繼承時,按照繼承順序返回繼承順序的下一個類
    pass

## (這裡需要介紹的是,當類繼承多個類時,python3中是按照廣度優先演算法,即在類ChildC的繼承關係中,會先找到靠近其的基類ChildA,然後繼承其的初始化函式__init__(),就不會再繼承ChildB的初始化函式)

c = ChildC() #例項化物件
print(c.__class__.__mro__) #物件c的繼承順序應該是 ChildC---ChildA---ChildB---Base---object

輸出結果:

Enter A
Enter B
Base create
Leave B
Leave A
(<class '__main__.ChildC'>, <class '__main__.ChildA'>, <class '__main__.ChildB'>, <class '__main__.Base'>, <class 'object'>)

整個執行過程,當例項化物件c時,按照類的繼承順序,先初始化類ChildC(),由於C中未定義初始化函式__init__(),因此直接呼叫其繼承的基類ChildA的__init__()初始化方法,執行到程式碼行第8行時,按照繼承順序super(ChildA,self)返回的是類ChildB(),因此,super(ChildA,self).__init__() == ChildB().__init__(self),因此就可以理解產生輸出結果的原理。

從super()方法中可以看出,super()的第一個引數可以是繼承鏈(繼承順序)中的任意一個類的名字,也可以不填,不填時第一個引數預設為當前類,即程式碼第10行 super(ChildA,self).__init__() ==super().__init__(),其返回值為在繼承鏈中輸入引數類的下一個類。

結論:

  • super()用來繼承基類的屬性和方法
  • 單繼承時,super().__init__() 和 父類.__init__()實現的功能是類似的
  • super不是父類,而是繼承順序的下一個類
  • super()可以避免重複呼叫