# Python多繼承的坑與MRO C3廣度優先算法

Python的繼承

Python有單繼承與多繼承。單繼承即子類繼承於一個類，多繼承即子類繼承於多個類，多繼承會比較少遇到，本章節主要講單繼承。

Python 總是首先查找對應類的方法，如果它不能在派生類中找到對應的方法，它纔開始到基類中逐個查找。（先在本類中查找調用的方法，找不到纔去基類中找） Python單繼承的案例：

``````class Animal(object):
def __init__(self, name, age):
self.name = name
self.age = age

def call(self):
print(self.name, '會叫')

class Cat(Animal):
def __init__(self,name,age,sex):
super(Cat, self).__init__(name,age)  # 不要忘記從Animal類執行初始化
self.sex=sex

if __name__ == '__main__':
c = Cat('喵喵', 2, '男')
c.call()

# 輸出 喵喵 會叫 ，Cat繼承了父類Animal的方法 ``````

``````class Plant:
def __init__(self, color):
print("init Plant start")
self.color = color
print("init Plant end")

def show(self):
print("The Plant color is:", self.color)

class Fruit:
def __init__(self, color):
print("init Fruit start")
self.color = color
print("init Fruit end")

def show(self):
print("The Fruit color is:", self.color)

class Melon(Fruit):
def __init__(self, color):
print("init Melon start")
super(Melon, self).__init__(color)
self.color = color
print("init Melon end")

def show(self):
print("The Melon color is:", self.color)

class Mango(Fruit, Plant):
def __init__(self, color):
print("init Mango start")
Plant.__init__(self, color)
Fruit.__init__(self, color)
self.color = color
print("init Mango end")

def show_color(self):
print("The Mango color is:", self.color)

class Watermelon(Melon, Plant):
def __init__(self, color):
print("init Watermelon start")
Melon.__init__(self, color)
Plant.__init__(self, color)
self.color = color
print("init Watermelon end")

def show_color(self):
print("The Watermelon color is:", self.color)

if __name__ == "__main__":
mango = Mango("yellow")
mango.show()

watermelon = Watermelon("red")
watermelon.show()``````

``````init Mango start
init Plant start
init Plant end
init Fruit start
init Fruit end
init Mango end
The Fruit color is: yellow

init Watermelon start
init Melon start
init Fruit start
init Fruit end
init Melon end
init Plant start
init Plant end
init Watermelon end
The Melon color is: red``````

Mango類即使初始化順序先初始化了Plant，再初始化Fruit類，但是執行的同名方法的順序仍然按定義該類是括號中的繼承順序；

Watermelon類也是按括號中的繼承順序來執行同名方法，但是執行的Melon類同名方法中，即使有該執行的Melon類的父類Fruit類也有同名方法，但還是優先執行該Melon類，這與一般的單繼承規則一致。 總結如下：

• 定義派生類時，需要注意圓括號中繼承父類的順序，若是父類中有相同的方法名，而在子類使用時未指定，python從左至右搜索 即方法在子類中未找到時，從左到右查找父類中是否包含方法；
• 如果繼承的父類中，該父類還繼承了別的父類，則調用同名方法時是調用最先訪問到的同名方法；
• 支持多層父類繼承，子類會繼承父類所有的屬性和方法，包括父類的父類的所有屬性 和 方法。

``````class Plant(object):
def __init__(self, color):
print("init Plant start")
self.color = color
print("init Plant end")

def show(self):
print("The Plant color is:", self.color)

class Fruit(object):
def __init__(self, color):
print("init Fruit start")
self.color = color
print("init Fruit end")

def show(self):
print("The Fruit color is:", self.color)

class Melon(Fruit):
def __init__(self, color):
print("init Melon start")
super(Melon, self).__init__(color)
self.color = color
print("init Melon end")

def show(self):
print("The Melon color is:", self.color)

class Mango(Fruit, Plant):
def __init__(self, color):
print("init Mango start")
super(Mango, self).__init__(color)
self.color = color
print("init Mango end")

def show_color(self):
print("The Mango color is:", self.color)

class Watermelon(Melon, Plant):
def __init__(self, color):
print("init Watermelon start")
super(Watermelon, self).__init__(color)
self.color = color
print("init Watermelon end")

def show_color(self):
print("The Watermelon color is:", self.color)

if __name__ == "__main__":
mango = Mango("yellow")
mango.show()

watermelon = Watermelon("red")
watermelon.show()``````

``````init Mango start
init Fruit start
init Fruit end
init Mango end
The Fruit color is: yellow
init Watermelon start
init Melon start
init Fruit start
init Fruit end
init Melon end
init Watermelon end
The Melon color is: red``````

``````class Fruit(object):
def __init__(self, color):
super().__init__(color)
print("init Fruit start")
self.color = color
print("init Fruit end")

def show(self):
print("The Fruit color is:", self.color)``````

Python 中針對 類 提供了一個內置屬性 mro 可以查看方法搜索順序 MRO 是 method resolution order，主要用於在多繼承時判斷 方法、屬性 的調用 路徑 Python2.3以上，MRO算法就已經改爲了廣度優先，防止最頂級的類被多次實例化而耗費資源：

• 實例本身(instance)
• 類(class)
• super class, 繼承關係越近, 越先定義, 優先級越高. 例如我們執行print(Mango.__mro__)會得到如下返回： (, , , )

Python多繼承的注意事項

``````1. 按順序繼承，哪個父類在最前面且它又有自己的構造函數，就繼承它的構造函數；
2. 如果最前面第一個父類沒有構造函數，則繼承第2個的構造函數，第2個沒有的話，再往後找，以此類推。``````

【雲棲號在線課堂】每天都有產品技術專家分享！

【雲棲號在線課堂 社羣】https://c.tb.cn/F3.Z8gvnK