1. 程式人生 > >python - 多繼承

python - 多繼承

多繼承
子類擁有一個父類叫做單繼承
子類可以擁有多個父類,並且具有所有父類的屬性和方法
例如:孩子會繼承自己父親和母親的特性

class A:
    def test(self):
        print('test 方法')


class B:
    def demo(self):
        print('demo 方法')


class D:
    def haha(self):
        print('!!!!!!')


class C(A,B,D):	
# A,B,D都是C的父類
    pass

c = C()
c.test()
c.demo()
c.haha()

輸出:

test 方法
demo 方法
!!!!!!

多繼承的注意事項:
問題的提出:
如果不同的父類中存在同名的方法,子類物件在呼叫方法時,會呼叫哪一個父類中的方法呢?
父類中方法名相同,會呼叫在子類中最先呼叫的類

(提示:開發時,應儘量避免這種容易產生混淆的情況)
如果父類之間存在同名的屬性或方法,因該儘量避免使用多繼承

例如:

class A:
    def test(self):
        print('A----test 方法')
    def demo(self):
        print('A----demo 方法')

class B:
    def test(self):
        print('B----test 方法')
    def demo(self):
        print('B----demo 方法')


class C(B,A):
    pass

c = C()
c.test()
c.demo()

輸出:

B----test 方法
B----demo 方法

如何避免屬性同名?

class Parent(object):
    def __init__(self,name):
        print('parent的init開始被呼叫')
        self.name = name
        print('parent的init結束被呼叫')

class Son1(Parent):
    def __init__(self,name,age):
        print('Son1的init開始被呼叫')
        self.age = age
        Parent.__init__(self,name)
        # Son1有parent的屬性
        print('Son1的init結束被呼叫')

class Son2(Parent):
    def __init__(self,name,gender):
        print('Son2的init開始被呼叫')
        self.gender = gender
        Parent.__init__(self,name)
        # Son2有parent的屬性
        print('Son2的init結束被呼叫')

class Grandson(Son1,Son2):
    def __init__(self,name,age,gender):
        print('grandson的init開始被呼叫')
        Son1.__init__(self,name,age)
        Son2.__init__(self,name,gender)
        # Grandson有Son1和Son2的屬性
        print('grandson的init結束被呼叫')


gs = Grandson('grandson',18,'男')
print('姓名:',gs.name)
print('年齡:',gs.age)
print('性別:',gs.gender)

在這裡插入圖片描述

也可以用super()解決多繼承的難題:
新式類:呼叫的順序為廣度優先
舊式類:呼叫順順序為深度優先
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 Womam(Person):
    def __init__(self):
        print('我是女的我要好好學習')
    def study(self):
        print('我要學好英語')
        super().study()

class Son(Man,Womam):
    def __init__(self):
        print('我是兒子我要好好學習')

    def study(self):
        print('我要學好化學和物理')
        # Womam.study(self)
        # Man.study(self)
        super().study()
print(Son.mro())
son1 = Son()
son1.study()

輸出:

[<class '__main__.Son'>, <class '__main__.Man'>, <class '__main__.Womam'>, <class '__main__.Person'>, <class 'object'>]		# mro順序
我是兒子我要好好學習	# Son 屬性
我要學好化學和物理		# Son 方法
我要學好數學	# Man方法
我要學好英語	# Woman方法
我要好好學習語言	# Person方法

super實現原理:通過c3演算法,生成mro(method resolution order)列表,根據列表中元素順序查詢呼叫
super()不是指父類 而是指以例項化物件為起點的mro序列中的下一個
  
簡潔點的三個原則就是:
子類在父類前,所有類不重複呼叫,從左到右

下面這段程式很複雜,可以用debug進行除錯。

class A():
    def go(self):
        print('go A go!')
    def stop(self):
        print('stop A stop!')
    def pause(self):
        raise Exception('Not Implemented')

class B(A):
    def go(self):
        super(B, self).go()
        print('go B go!')

class C(A):
    def go(self):
        super(C, self).go()
        print('go C go!')

    def stop(self):
        super(C, self).stop()
        print('stop C stop!')

class D(B,C):
    def go(self):
        super(D, self).go()
        print('go D go!')
    def stop(self):
        super(D,self).stop()
    def pause(self):
        print('wait D wait!')

class E(B,C):
    pass

print(D.mro())
a = A()
b = B()
c = C()
d = D()
d.go()
d.stop()
d.pause()
e = E()

輸出:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
go A go!
go C go!
go B go!
go D go!
stop A stop!
stop C stop!
wait D wait!