Python多重繼承的使用小結(jié)
繼承是面向?qū)ο缶幊讨械囊粋€(gè)特性,允許類(lèi)繼承另一個(gè)類(lèi)的屬性和方法。在 Python 中,你可以實(shí)現(xiàn)不同類(lèi)型的繼承,比如單繼承、多繼承和多層繼承。本章詳細(xì)介紹了多重繼承。
什么是多重繼承?
多重繼承是一種繼承方式,其中單個(gè)類(lèi)可以繼承多個(gè)父類(lèi)的屬性和方法。當(dāng)你想把多個(gè)類(lèi)的功能整合到一個(gè)類(lèi)里時(shí),這可以用。下圖展示了多重繼承 −

多重繼承的例子
在下面的例子中,子類(lèi)繼承了父類(lèi)和母類(lèi) -
class Father:
def skill1(self):
print("Father's skill: Gardening")
class Mother:
def skill2(self):
print("Mother's skill: Cooking")
class Child(Father, Mother):
pass
c = Child()
c.skill1()
c.skill2()上述代碼的輸出為−
Father's skill: Gardening
Mother's skill: Cooking
解釋:在這個(gè)例子中,子類(lèi)可以同時(shí)訪問(wèn)其父類(lèi)的 skill1() 和 skill2() 方法。當(dāng)我們創(chuàng)建 Child 實(shí)例并調(diào)用 skill1() 時(shí),它執(zhí)行的是 Father 類(lèi)的方法。同樣,當(dāng)我們調(diào)用 skill2() 時(shí),它執(zhí)行的是母類(lèi)的方法。
但是,如果兩個(gè)父類(lèi)都有同名的方法,會(huì)發(fā)生什么?誰(shuí)會(huì)被處決?這就是方法分辨率次序(MRO)發(fā)揮作用的地方。
多重繼承的方法解析順序
如果同名方法在多個(gè)父類(lèi)中定義,Python 會(huì)遵循特定的順序來(lái)決定執(zhí)行哪個(gè)方法。該命令被稱為方法解析令(MRO)。該階數(shù)由C3線性化算法(也稱為MRO)確定。MRO命令如下所示。
- 首先,Python 在子類(lèi)中查找方法。
- 如果找不到,它會(huì)按列表的順序搜索父類(lèi)。
- 直到找到方法或搜索所有類(lèi)為止。
多重繼承最核心的問(wèn)題是:當(dāng)多個(gè)父類(lèi)有同名方法時(shí),子類(lèi)調(diào)用該方法會(huì)優(yōu)先執(zhí)行哪個(gè)父類(lèi)的?Python 通過(guò)MRO(Method Resolution Order,方法解析順序) 來(lái)解決這個(gè)問(wèn)題,遵循 “從左到右、深度優(yōu)先” 的原則(Python3 中是 C3 算法,本質(zhì)是優(yōu)化后的深度優(yōu)先)。
你可以用mro()方法或__mro__屬性檢查對(duì)象的MRO。例如−
print(Child.mro()) Output: [<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>]
示例
在以下示例中,Child 類(lèi)繼承了 Father 和 Mother 類(lèi)的 skill() 方法,但調(diào)用的是 mother's 方法。
class Father:
def skill(self):
print("Father's skill: Gardening")
class Mother:
def skill(self):
print("Mother's skill: Cooking")
class Child(Father, Mother):
pass
c = Child()
c.skill()解釋:當(dāng)技能方法在子類(lèi)實(shí)例c中被調(diào)用時(shí),它首先會(huì)在子類(lèi)中查找該方法。由于子類(lèi)沒(méi)有技能方法,它會(huì)按父類(lèi)排序(父類(lèi),然后是母類(lèi))搜索父類(lèi),并執(zhí)行第一個(gè)找到的。
上述代碼的輸出為−
Father's skill: Gardening
在多重繼承中使用 super()
super() 函數(shù)被子類(lèi)用于調(diào)用父類(lèi)的方法。如果你在多重繼承情況下的方法中使用 super(),它會(huì)嚴(yán)格按照 MRO 命令來(lái)決定調(diào)用哪個(gè)方法。
示例
在這個(gè)例子中,我們有一個(gè)包含四個(gè)類(lèi)的類(lèi)層級(jí)結(jié)構(gòu):A、B、C 和 D。類(lèi) D 繼承自 B 和 C,證明了多重繼承。
class A:
def show(self):
print("Class A")
class B(A):
def show(self):
print("Class B")
super().show()
class C(A):
def show(self):
print("Class C")
super().show()
class D(B, C):
def show(self):
print("Class D")
super().show()
d = D()
d.show()上述代碼的輸出為−
Class D
Class B
Class C
Class A
解釋:D類(lèi)的MRO為[D, B, C, A, 對(duì)象]。這意味著當(dāng)某個(gè)方法在D實(shí)例上被調(diào)用時(shí),Python會(huì)先在D中尋找該方法,然后是B,再是C,最后是A。因此,“D類(lèi)”、“B類(lèi)”、“C類(lèi)”和“A類(lèi)”將按該順序印刷。
多重繼承中的鉆石問(wèn)題
鉆石問(wèn)題是多重繼承中常見(jiàn)的問(wèn)題。當(dāng)兩個(gè)父類(lèi)繼承同一個(gè)基類(lèi),而子類(lèi)繼承兩個(gè)父類(lèi)時(shí),就會(huì)出現(xiàn)這種情況。下圖展示了這個(gè)場(chǎng)景:

鉆石問(wèn)題導(dǎo)致在繼承基類(lèi)時(shí),該調(diào)用哪個(gè)方法產(chǎn)生混淆。Python 通過(guò)遵循我們之前討論過(guò)的方法解析順序(mro)來(lái)解決這個(gè)問(wèn)題。讓我們看看鉆石問(wèn)題的例子 −
示例
下面的代碼演示了鉆石問(wèn)題以及Python如何通過(guò)MRO解決 −
class A:
def show(self):
print("Class A")
class B(A):
def show(self):
print("Class B")
class C(A):
def show(self):
print("Class C")
class D(B, C):
pass
d = D()
d.show()上述代碼的輸出為−
Class B
解釋:D類(lèi)的MRO命令為[D, B, C, A]。所以,當(dāng)調(diào)用 d.show() 時(shí),它首先在類(lèi) D 里查找,但那里沒(méi)有 show 函數(shù),于是它會(huì)去 class B,找到 show 函數(shù)并執(zhí)行它。
多重繼承的坑與最佳實(shí)踐
1. 避免的問(wèn)題
- 鉆石繼承(菱形繼承):多個(gè)父類(lèi)最終繼承自同一個(gè)基類(lèi),可能導(dǎo)致重復(fù)調(diào)用或?qū)傩詻_突(Python3 的 C3 算法已解決,但仍需謹(jǐn)慎)。
- 代碼可讀性差:過(guò)多父類(lèi)會(huì)讓代碼邏輯混亂,難以維護(hù)。
2. 最佳實(shí)踐
- 盡量少用多重繼承:能用單一繼承 + 組合 / 接口實(shí)現(xiàn)的,就不用多重繼承。
- 使用 Mixin 模式:將通用功能封裝成 Mixin 類(lèi)(僅包含方法,無(wú)屬性),作為輔助繼承,主邏輯仍用單一繼承。
# Mixin類(lèi):僅提供通用功能
class SwimMixin:
def swim(self):
print("會(huì)游泳")
# 主父類(lèi)
class Person:
def eat(self):
print("會(huì)吃飯")
# 子類(lèi):主繼承Person,輔助繼承SwimMixin
class Student(Person, SwimMixin):
pass
stu = Student()
stu.eat() # 輸出:會(huì)吃飯
stu.swim() # 輸出:會(huì)游泳多重繼承的利弊
多重繼承有若干優(yōu)缺點(diǎn) -
| 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|
| 提升代碼模塊化和可復(fù)用性。 | 增加了復(fù)雜度,可能導(dǎo)致模糊性。 |
| 允許將多個(gè)類(lèi)別的功能組合在一起。 | 這可能導(dǎo)致鉆石問(wèn)題。 |
| 可以創(chuàng)建復(fù)雜的現(xiàn)實(shí)關(guān)系 | 調(diào)試和維護(hù)更難。 |
多重繼承是一種面向?qū)ο缶幊痰母拍?,其中?lái)自多個(gè)父類(lèi)的方法可以被子類(lèi)繼承。我們討論了 Python 如何利用方法解析順序(MRO)處理多重繼承,以及如何使用 super() 函數(shù)。鉆石問(wèn)題在多重繼承中很常見(jiàn),但 Python 通過(guò) MRO 解決了這個(gè)問(wèn)題。多重繼承的主要缺點(diǎn)是讓職業(yè)層級(jí)結(jié)構(gòu)更復(fù)雜且更難理解。
結(jié)論
- Python 支持多重繼承,子類(lèi)可繼承多個(gè)父類(lèi)的屬性和方法,寫(xiě)法為
class 子類(lèi)(父類(lèi)1, 父類(lèi)2, ...)。 - 同名方法的執(zhí)行順序遵循 MRO 規(guī)則,可通過(guò)
__mro__查看,默認(rèn)優(yōu)先執(zhí)行左側(cè)父類(lèi)的方法。 - 實(shí)際開(kāi)發(fā)中應(yīng)盡量少用多重繼承,推薦 Mixin 模式(輔助功能 + 主繼承),保證代碼可讀性和可維護(hù)性。
到此這篇關(guān)于Python多重繼承的使用小結(jié)的文章就介紹到這了,更多相關(guān)Python多重繼承內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用python解決mysql視圖導(dǎo)入導(dǎo)出依賴的問(wèn)題
這篇文章主要給大家介紹了關(guān)于利用python解決mysql視圖導(dǎo)入導(dǎo)出依賴的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
10 行Python 代碼實(shí)現(xiàn) AI 目標(biāo)檢測(cè)技術(shù)【推薦】
這篇文章主要介紹了10 行Python 代碼,實(shí)現(xiàn) AI 目標(biāo)檢測(cè)技術(shù),看完了代碼,我們?cè)谝黄鹆牧哪繕?biāo)檢測(cè)背后的技術(shù)背景,并解讀這10行Python代碼的由來(lái)和實(shí)現(xiàn)原理。感興趣的朋友跟隨小編一起看看吧2019-06-06
Python+PyQt5打造一個(gè)Excel批量列處理工具
在日常的辦公中,我們經(jīng)常會(huì)遇到需要批量處理Excel文件的情況,今天我們就用 Python + PyQt5 + Pandas 打造一款圖形化的Excel批量列處理工具,不僅支持一鍵拖拽文件,還能動(dòng)態(tài)選擇列名、添加多條處理規(guī)則,幫你徹底告別重復(fù)勞動(dòng)2026-04-04
python之如何使用openpyxl設(shè)置單元格樣式
這篇文章主要介紹了python之如何使用openpyxl設(shè)置單元格樣式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
零基礎(chǔ)寫(xiě)python爬蟲(chóng)之urllib2中的兩個(gè)重要概念:Openers和Handlers
文章首先介紹了urllib2的2個(gè)方法,然后詳細(xì)介紹了urllib2中的2個(gè)重要概念Openers和Handlers的相關(guān)知識(shí),希望能對(duì)大家有所幫助2014-11-11
python通過(guò)cookie模擬已登錄狀態(tài)的初步研究
對(duì)于那些需要在登錄環(huán)境下進(jìn)行的爬蟲(chóng)操作,模擬登陸或偽裝已登錄狀態(tài)是一個(gè)剛性需求。這篇文章主要介紹了python通過(guò)cookie模擬已登錄狀態(tài)的相關(guān)資料,需要的朋友可以參考下2016-11-11

