1. 程式人生 > >python3面向物件(2)之super()

python3面向物件(2)之super()

super()是一個什麼鬼?幹什麼用的?開啟菜鳥教程看一下super()的簡介;第一句話就是:super()函式是用來呼叫父類(超類)的一個方法。嗯哦;原來是一個函式可以返回一個父類的方法:於是我就這樣理解了,那麼如果是多繼承呢,是返回所有父類的被呼叫的方法嗎?一個疑問?看看下面的程式碼(先定義一個人類,然後定義一個男人,一個女人,一個兒子)

class Person(object):     #定義一個人類,繼承objec
    def __init__(self):
        print("我要好好學習")

    def study(self):
        print("我要學好語言")


class man(Person):   #定義一個男人,繼承人類
    def __init__(self):
        print("我是男人我要好好學習")

    def study(self):
        print("我要學好數學")
        


class woman(Person):    #定義一個女人,繼承人類
    def __init__(self):
        print("我是女人我要好好學習")

    def study(self):
        print("我要學好英語")
      

class son(man,woman):  #定義一個兒子,繼承男人和女人
    def __init__(self):
        print("我是兒子我要好好學習")

    def study(self):
        print("我要學好化學和物理")
# woman.study(self) # man.study(self) super().study() # def study1(self): # print("我要學好英語") son1 = son() son1.study() # son1.study1()
解釋:先定義一個人類,定義一個方法:我要學好語言;然後定義一個男人:我要學好數學;再定義一個女人:我要學好英語;最後定義一個兒子學好化學和物理;在定義方法的時候我們都使用了study函式;所以子類的函式
會覆蓋父類的函式;最後例項化一個son1的物件呼叫study函式只會輸出:我要學好化學和物理;但是這個時代光會這兩門也不行啊;還得學好英語啊,那麼怎麼辦呢? ok 簡單

在這個son的類中增加一個study1函式不就完了嘛,嗯,對確實完了;但是這樣卻增加了不必要的程式碼啊,學習英語這件事woman類中不是有了嗎?我們不能直接使用這裡的嗎?當然可以,於是有了第二種方法:

在son的類中的study函式中增加了 woman.study(self) 這句好相當於直接呼叫woman類中的study函式 同理也可以直接呼叫man類中的study函式;這樣就不用建立新函數了;這種等於直接呼叫。我們還可以使用另外
一種方式來呼叫man和woman中的study函式即:super().study();前面兩種我們已經註釋掉了我們只研究最後一種;即出現了上面的程式碼;那麼這段程式碼會
出現什麼呢?(反正我一開始覺得super()不是呼叫父類的方法嘛,既然son有兩個父類,兩個父類的study函式一起呼叫了唄,可是結果呢)

 

 程式碼執行結果:

我是兒子我要好好學習
我要學好化學和物理
我要學好數學

 噫噫噫,不對啊,和我想的不一樣啊,只返回了man類中的方法;沒有返回woman類中的方法啊;這是什麼情況呢?一百的問號????

於是查看了很多的部落格,畢竟還是有很多大神的嘛我們要向前輩們學習啊,於是對super()又有了新的認識:我們返回文章的第一句話,super()是個什麼鬼?從新解釋一下:super()不是一個函式而是一個類,super()相當於這個類呼叫了自己的初始化函式,返回了一個物件;這個物件是幹嘛的呢,用來呼叫例項化物件中的mro()序列中的下一個  的  類的

指定的類中的方法(mro()返回的是一個:方法解析順序列表)估計又懵了,那麼我們先列印一下:son.mro()

[<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]

實際上打印出來的就是son的繼承父類的順序(son---man---woman---Person---object)

那麼以本例來說在son中寫了super(),那麼son的下一個mro當然就是man類,所以就返回了man類中的study方法了。這就是上面那個疑問的解答了;那麼問題又來了如果我在man類中也寫了super().study(),那麼接下來會列印什麼呢?無非就兩個可能一個是列印Person中的sutdy方法另一個可能就是列印woman類中的study方法(為什麼是這兩種呢,如果我們是以son為出發點man的下一個mro當然是woman;但是我們現在是把super().study()寫在了man類中這個時候好像以man類為出發點也說的過去啊,那麼我們先列印一下man,mro()。)

class man(Person):
    def __init__(self):
        print("我是男人我要好好學習")

    def study(self):
        print("我要學好數學")
        super().study()

結果:
[<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]

 果然man的下一個mro是Person而不是woman啊,如果我們執行上面的程式碼最終到底是列印person呢還是woman呢?看結果:

我是兒子我要好好學習
[<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
[<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
我要學好化學和物理
我要學好數學
我要學好英語

 打印出來的是我要學好英語是woman中的(而不是person中的);如果我們在woman類中也一起寫上super(),那麼:

class Person(object):
    def __init__(self):
        print("我要好好學習")

    def study(self):
        print("我要學好語言")


class man(Person):
    def __init__(self):
        print("我是男人我要好好學習")

    def study(self):
        print("我要學好數學")
        super().study()


class woman(Person):
    def __init__(self):
        print("我是女人我要好好學習")

    def study(self):
        print("我要學好英語")
        super().study()

class son(man,woman):
    def __init__(self):
        print("我是兒子我要好好學習")

    def study(self):
        print("我要學好化學和物理")
        # woman.study(self)
        # man.study(self)

        super().study()

    # def study1(self):
    #     print("我要學好英語")


son1 = son()
print(son.mro())
print(man.mro())
son1.study()
# son1.study1()

 結果:

我是兒子我要好好學習
[<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
[<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
我要學好化學和物理
我要學好數學
我要學好英語
我要學好語言

 看一下結果就知道了先列印了man類中的study方法,之後列印了woman類中的方法;最後列印了Person類中的study方法;所以到這裡暫時得到一個結論:super()不是指父類(對於man類來說Person應該是父類)而只指以例項化物件為起點的mro序列中的下一個。

那麼我們把上面的程式碼再來改一改,如果我把man類中的super()註釋掉了,但是woman類中保留著super()會又什麼樣的的結果呢:

class Person(object):
    def __init__(self):
        print("我要好好學習")

    def study(self):
        print("我要學好語言")


class man(Person):
    def __init__(self):
        print("我是男人我要好好學習")

    def study(self):
        print("我要學好數學")
        # super().study()

class woman(Person):
    def __init__(self):
        print("我是女人我要好好學習")

    def study(self):
        print("我要學好英語")
        super().study()

class son(man,woman):
    def __init__(self):
        print("我是兒子我要好好學習")

    def study(self):
        print("我要學好化學和物理")
        # woman.study(self)
        # man.study(self)

        super().study()

    # def study1(self):
    #     print("我要學好英語")


son1 = son()

print(son.mro())
print(man.mro())

son1.study()


# son1.study1()

 結果:

我是兒子我要好好學習
[<class '__main__.son'>, <class '__main__.man'>, <class '__main__.woman'>, <class '__main__.Person'>, <class 'object'>]
[<class '__main__.man'>, <class '__main__.Person'>, <class 'object'>]
我要學好化學和物理
我要學好數學

 結果是man類中的sutdy方法打印出來瞭然而woman和Person類中的study方法沒有打印出來;相當與 son--man--woman中在man這裡打斷了,然後後面的也就不執行了。

好吧就到這裡吧由於剛開始學習python,對於super()理解的還有很多不到位的地方;以後這篇文章還需要改進,暫時理解到這個程度。