首頁  >  文章  >  後端開發  >  關於python類別中super()和__init__()的區別說明

關於python類別中super()和__init__()的區別說明

高洛峰
高洛峰原創
2017-03-16 16:08:291372瀏覽

單一繼承super()和init()實作的函數是類似的

class Base(object):
    def init(self):
        print 'Base create'
class childA(Base):
    def init(self):
        print 'creat A ',
        Base.init(self)
class childB(Base):
    def init(self):
        print 'creat B ',
        super(childB, self).init()
base = Base()
a = childA()
b = childB()

輸出結果:

Base create
creat A  Base create
creat B  Base create

差異是使用super()繼承時不用明確引用基底類別。


super()只能用於新式類別中


#把基類改為舊式類,即不繼承任何基底類別

class Base():
    def init(self):
        print 'Base create'

執行時,在初始化b時就會報錯:

super(childB, self).init()
TypeError: must be type, not classobj


super不是父類,而是繼承順序的下一個類別


在多重繼承時會涉及繼承順序,super()相當於返回繼承順序的下一個類,而不是父類,類似於這樣的功能:

def super(class_name, self):
    mro = self.class.mro()
    return mro[mro.index(class_name) + 1]

mro()用來得到類別的繼承順序。 例如:

class Base(object):
    def init(self):
        print 'Base create'
class childA(Base):
    def init(self):
        print 'enter A '
        # Base.init(self)
        super(childA, self).init()
        print 'leave A'
class childB(Base):
    def init(self):
        print 'enter B '
        # Base.init(self)
        super(childB, self).init()
        print 'leave B'
class childC(childA, childB):
    pass
c = childC()
print c.class.mro

輸出結果如下:

enter A 
enter B 
Base create
leave B
leave A
(<class &#39;main.childC&#39;>, <class &#39;main.childA&#39;>, <class &#39;main.childB&#39;>, <class &#39;main.Base&#39;>, <type &#39;object&#39;>)

supder和父類別沒有關聯,因此執行順序是A —> B—>—>Base


#執行過程相當於:初始化childC()時,先會去呼叫childA的建構方法中的super(childA, self).init(), super(childA, self)傳回目前類別的繼承順序中childA後的一個類別childB;然後再執行childB().init(),這樣順序執行下去。


在多重繼承裡,如果把childA()中的super(childA, self).init() 換成Base._init_(self),在執行時,繼承childA後就會直接跳到Base類別裡,而略過了childB:

enter A 
Base create
leave A
(<class &#39;main.childC&#39;>, <class &#39;main.childA&#39;>, <class &#39;main.childB&#39;>, <class &#39;main.Base&#39;>, <type &#39;object&#39;>)

從super()方法可以看出,super()的第一個參數可以是繼承鏈中任意一個類別的名字,


如果是本身就會依序繼承下一個類別;


##如果是繼承鏈裡之前的類別便會無限

遞歸下去;


如果是繼承鏈裡之後的類別便會忽略繼承鏈匯總本身和傳入類別之間的類別;


例如將childA()中的super改為:super(childC, self).init(),程式就會無限遞歸下去。 如:

  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
RuntimeError: maximum recursion depth exceeded while calling a Python object


super()可以避免重複呼叫


如果childA基礎Base, childB繼承childA和Base ,如果childB需要呼叫Base的init()方法時,就會導致init()被執行兩次:

class Base(object):
    def init(self):
        print &#39;Base create&#39;
class childA(Base):
    def init(self):
        print &#39;enter A &#39;
        Base.init(self)
        print &#39;leave A&#39;
class childB(childA, Base):
    def init(self):
        childA.init(self)
        Base.init(self)
b = childB()

Base的init()方法被執行了兩次

enter A 
Base create
leave A
Base create


使用super()是可避免重複呼叫

class Base(object):
    def init(self):
        print &#39;Base create&#39;
class childA(Base):
    def init(self):
        print &#39;enter A &#39;
        super(childA, self).init()
        print &#39;leave A&#39;
class childB(childA, Base):
    def init(self):
        super(childB, self).init()
b = childB()
print b.class.mro()
enter A 
Base create
leave A
[<class &#39;main.childB&#39;>, <class &#39;main.childA&#39;>, <class &#39;main.Base&#39;>, <type &#39;object&#39;>]


#

以上是關於python類別中super()和__init__()的區別說明的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn