python函數(shù)繼承系列 python 繼承方法

Python面向?qū)ο缶幊讨^承與多態(tài)詳解

Python面向?qū)ο缶幊讨^承與多態(tài)詳解

創(chuàng)新互聯(lián)公司一直在為企業(yè)提供服務(wù),多年的磨煉,使我們?cè)趧?chuàng)意設(shè)計(jì),全網(wǎng)整合營(yíng)銷(xiāo)推廣到技術(shù)研發(fā)擁有了開(kāi)發(fā)經(jīng)驗(yàn)。我們擅長(zhǎng)傾聽(tīng)企業(yè)需求,挖掘用戶(hù)對(duì)產(chǎn)品需求服務(wù)價(jià)值,為企業(yè)制作有用的創(chuàng)意設(shè)計(jì)體驗(yàn)。核心團(tuán)隊(duì)擁有超過(guò)十年以上行業(yè)經(jīng)驗(yàn),涵蓋創(chuàng)意,策化,開(kāi)發(fā)等專(zhuān)業(yè)領(lǐng)域,公司涉及領(lǐng)域有基礎(chǔ)互聯(lián)網(wǎng)服務(wù)雙線服務(wù)器托管、成都app軟件開(kāi)發(fā)、手機(jī)移動(dòng)建站、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)絡(luò)整合營(yíng)銷(xiāo)。

本文實(shí)例講述了Python面向?qū)ο缶幊讨^承與多態(tài)。分享給大家供大家參考,具體如下:

Python 類(lèi)的繼承

在OOP(Object Oriented Programming)程序設(shè)計(jì)中,當(dāng)我們定義一個(gè)class的時(shí)候,可以從某個(gè)現(xiàn)有的class 繼承,新的class稱(chēng)為子類(lèi)(Subclass),而被繼承的class稱(chēng)為基類(lèi)、父類(lèi)或超類(lèi)(Base class、Super class)。

我們先來(lái)定義一個(gè)class Person,表示人,定義屬性變量 name 及 sex (姓名和性別);

定義一個(gè)方法print_title():當(dāng)sex是male時(shí),print man;當(dāng)sex 是female時(shí),print woman。參考如下代碼:

class Person(object):

def __init__(self,name,sex):

self.name = name

self.sex = sex

def print_title(self):

if self.sex == "male":

print("man")

elif self.sex == "female":

print("woman")

class Child(Person): # Child 繼承 Person

pass

May = Child("May","female")

Peter = Person("Peter","male")

print(May.name,May.sex,Peter.name,Peter.sex) # 子類(lèi)繼承父類(lèi)方法及屬性

May.print_title()

Peter.print_title()

而我們編寫(xiě) Child 類(lèi),完全可以繼承 Person 類(lèi)(Child 就是 Person);使用 class subclass_name(baseclass_name) 來(lái)表示繼承;

繼承有什么好處?最大的好處是子類(lèi)獲得了父類(lèi)的全部屬性及功能。如下 Child 類(lèi)就可以直接使用父類(lèi)的 print_title() 方法

實(shí)例化Child的時(shí)候,子類(lèi)繼承了父類(lèi)的構(gòu)造函數(shù),就需要提供父類(lèi)Person要求的兩個(gè)屬性變量 name 及 sex:

在繼承關(guān)系中,如果一個(gè)實(shí)例的數(shù)據(jù)類(lèi)型是某個(gè)子類(lèi),那它也可以被看做是父類(lèi)(May 既是 Child 又是 Person)。但是,反過(guò)來(lái)就不行(Peter 僅是 Person,而不是Child)。

繼承還可以一級(jí)一級(jí)地繼承下來(lái),就好比從爺爺?shù)桨职?、再到兒子這樣的關(guān)系。而任何類(lèi),最終都可以追溯到根類(lèi)object,這些繼承關(guān)系看上去就像一顆倒著的樹(shù)。比如如下的繼承樹(shù):

isinstance() 及 issubclass()

Python 與其他語(yǔ)言不同點(diǎn)在于,當(dāng)我們定義一個(gè) class 的時(shí)候,我們實(shí)際上就定義了一種數(shù)據(jù)類(lèi)型。我們定義的數(shù)據(jù)類(lèi)型和Python自帶的數(shù)據(jù)類(lèi)型,比如str、list、dict沒(méi)什么兩樣。

Python 有兩個(gè)判斷繼承的函數(shù):isinstance() 用于檢查實(shí)例類(lèi)型;issubclass() 用于檢查類(lèi)繼承。參見(jiàn)下方示例:

class Person(object):

pass

class Child(Person): # Child 繼承 Person

pass

May = Child()

Peter = Person()

print(isinstance(May,Child)) # True

print(isinstance(May,Person)) # True

print(isinstance(Peter,Child)) # False

print(isinstance(Peter,Person)) # True

print(issubclass(Child,Person)) # True

Python 類(lèi)的多態(tài)

在說(shuō)明多態(tài)是什么之前,我們?cè)?Child 類(lèi)中重寫(xiě) print_title() 方法:若為male,print boy;若為female,print girl

class Person(object):

def __init__(self,name,sex):

self.name = name

self.sex = sex

def print_title(self):

if self.sex == "male":

print("man")

elif self.sex == "female":

print("woman")

class Child(Person): # Child 繼承 Person

def print_title(self):

if self.sex == "male":

print("boy")

elif self.sex == "female":

print("girl")

May = Child("May","female")

Peter = Person("Peter","male")

print(May.name,May.sex,Peter.name,Peter.sex)

May.print_title()

Peter.print_title()

當(dāng)子類(lèi)和父類(lèi)都存在相同的 print_title()方法時(shí),子類(lèi)的 print_title() 覆蓋了父類(lèi)的 print_title(),在代碼運(yùn)行時(shí),會(huì)調(diào)用子類(lèi)的 print_title()

這樣,我們就獲得了繼承的另一個(gè)好處:多態(tài)。

多態(tài)的好處就是,當(dāng)我們需要傳入更多的子類(lèi),例如新增 Teenagers、Grownups 等時(shí),我們只需要繼承 Person 類(lèi)型就可以了,而print_title()方法既可以直不重寫(xiě)(即使用Person的),也可以重寫(xiě)一個(gè)特有的。這就是多態(tài)的意思。調(diào)用方只管調(diào)用,不管細(xì)節(jié),而當(dāng)我們新增一種Person的子類(lèi)時(shí),只要確保新方法編寫(xiě)正確,而不用管原來(lái)的代碼。這就是著名的“開(kāi)閉”原則:

對(duì)擴(kuò)展開(kāi)放(Open for extension):允許子類(lèi)重寫(xiě)方法函數(shù)

對(duì)修改封閉(Closed for modification):不重寫(xiě),直接繼承父類(lèi)方法函數(shù)

子類(lèi)重寫(xiě)構(gòu)造函數(shù)

子類(lèi)可以沒(méi)有構(gòu)造函數(shù),表示同父類(lèi)構(gòu)造一致;子類(lèi)也可重寫(xiě)構(gòu)造函數(shù);現(xiàn)在,我們需要在子類(lèi) Child 中新增兩個(gè)屬性變量:mother 和 father,我們可以構(gòu)造如下(建議子類(lèi)調(diào)用父類(lèi)的構(gòu)造方法,參見(jiàn)后續(xù)代碼):

class Person(object):

def __init__(self,name,sex):

self.name = name

self.sex = sex

class Child(Person): # Child 繼承 Person

def __init__(self,name,sex,mother,father):

self.name = name

self.sex = sex

self.mother = mother

self.father = father

May = Child("May","female","April","June")

print(May.name,May.sex,May.mother,May.father)

若父類(lèi)構(gòu)造函數(shù)包含很多屬性,子類(lèi)僅需新增1、2個(gè),會(huì)有不少冗余的代碼,這邊,子類(lèi)可對(duì)父類(lèi)的構(gòu)造方法進(jìn)行調(diào)用,參考如下:

class Person(object):

def __init__(self,name,sex):

self.name = name

self.sex = sex

class Child(Person): # Child 繼承 Person

def __init__(self,name,sex,mother,father):

Person.__init__(self,name,sex) # 子類(lèi)對(duì)父類(lèi)的構(gòu)造方法的調(diào)用

self.mother = mother

self.father = father

May = Child("May","female","April","June")

print(May.name,May.sex,May.mother,May.father)

多重繼承

多重繼承的概念應(yīng)該比較好理解,比如現(xiàn)在需要新建一個(gè)類(lèi) baby 繼承 Child , 可繼承父類(lèi)及父類(lèi)上層類(lèi)的屬性及方法,優(yōu)先使用層類(lèi)近的方法,代碼參考如下:

class Person(object):

def __init__(self,name,sex):

self.name = name

self.sex = sex

def print_title(self):

if self.sex == "male":

print("man")

elif self.sex == "female":

print("woman")

class Child(Person):

pass

class Baby(Child):

pass

May = Baby("May","female") # 繼承上上層父類(lèi)的屬性

print(May.name,May.sex)

May.print_title() # 可使用上上層父類(lèi)的方法

class Child(Person):

def print_title(self):

if self.sex == "male":

print("boy")

elif self.sex == "female":

print("girl")

class Baby(Child):

pass

May = Baby("May","female")

May.print_title() # 優(yōu)先使用上層類(lèi)的方法

說(shuō)說(shuō) Python 的繼承

如果要編寫(xiě)的類(lèi)是另一個(gè)類(lèi)的特殊版本時(shí),那么就可以使用繼承 。原有的類(lèi)稱(chēng)為父類(lèi) , 新類(lèi)稱(chēng)為子類(lèi) 。 子類(lèi)繼承了父類(lèi)的所有屬性和方法, 同時(shí)子類(lèi)還可以自定義自己的屬性和方法。

定義子類(lèi)的實(shí)例時(shí), 可以通過(guò) 子類(lèi)的 __init__() 方法,給父類(lèi)的所有屬性賦值。

假設(shè)有這樣的一個(gè) User 類(lèi):

接著,我們定義一個(gè) Admin 類(lèi),讓它繼承 User 類(lèi):

運(yùn)行結(jié)果:

super() 是一個(gè)特殊函數(shù), 它會(huì)把父類(lèi)和子類(lèi)關(guān)聯(lián)起來(lái)。因?yàn)楦割?lèi)也稱(chēng)為超類(lèi) ( superclass),所以這個(gè)函數(shù)叫做 super。接著調(diào)用父類(lèi)的 __init__() 方法, 讓子類(lèi)包含父類(lèi)的所有屬性。

子類(lèi)除了擁有繼承父類(lèi)而來(lái)的屬性和方法之外,還可以自定義子類(lèi)自己的屬性和方法。

一般情況下,管理員賬號(hào)比普通賬號(hào),擁有更高級(jí)別的權(quán)限。因此,我們?yōu)?Admin 定義一個(gè)有別于 User 的 privileges 屬性,并定義一個(gè) “打印擁有的權(quán)限” 的新方法:

運(yùn)行結(jié)果:

對(duì)于繼承而來(lái)的父類(lèi)方法, 如果它不符合子類(lèi)所期望的行為,那么就可以對(duì)其重寫(xiě)。 只要在子類(lèi)中定義一個(gè)與父類(lèi)同名的方法,即可實(shí)現(xiàn)重寫(xiě)。

User 本身定義了一個(gè) “是否驗(yàn)證通過(guò)” 的方法,Admin 是管理員,所以需要在打印日志中特別標(biāo)注出來(lái),這時(shí)就需要重寫(xiě)父類(lèi)定義的方法:

運(yùn)行結(jié)果:

通過(guò)重寫(xiě)父類(lèi)方法, 我們就可以讓子類(lèi)即可以保留或改寫(xiě)從父類(lèi)取其精華,棄其“糟粕”啦。

當(dāng)實(shí)體越來(lái)越復(fù)雜,對(duì)應(yīng)的類(lèi)變得越來(lái)越大時(shí), 我們可以將這個(gè)大型類(lèi)拆分成多個(gè)可協(xié)同工作的小類(lèi)。

比如,賬號(hào)權(quán)限,其實(shí)即使是普通賬號(hào)也是有某些權(quán)限的。所以我們把權(quán)限定義為一個(gè)類(lèi),然后在 Admin 中使用它:

Python中繼承的理解與運(yùn)用?

9.5. 繼承

當(dāng)然,如果一種語(yǔ)言不支持繼承就,“類(lèi)”就沒(méi)有什么意義。派生類(lèi)的定義如下所示:

class DerivedClassName(BaseClassName):

命名 BaseClassName (示例中的基類(lèi)名)必須與派生類(lèi)定義在一個(gè)作用域內(nèi)。除了類(lèi),還可以用表達(dá)式,基類(lèi)定義在另一個(gè)模塊中時(shí)這一點(diǎn)非常有用:

class DerivedClassName(modname.BaseClassName):

派生類(lèi)定義的執(zhí)行過(guò)程和基類(lèi)是一樣的。構(gòu)造派生類(lèi)對(duì)象時(shí),就記住了基類(lèi)。這在解析屬性引用的時(shí)候尤其有用:如果在類(lèi)中找不到請(qǐng)求調(diào)用的屬性,就搜索基類(lèi)。如果基類(lèi)是由別的類(lèi)派生而來(lái),這個(gè)規(guī)則會(huì)遞歸的應(yīng)用上去。

派生類(lèi)的實(shí)例化沒(méi)有什么特殊之處: DerivedClassName() (示列中的派生類(lèi))創(chuàng)建一個(gè)新的類(lèi)實(shí)例。方法引用按如下規(guī)則解析:搜索對(duì)應(yīng)的類(lèi)屬性,必要時(shí)沿基類(lèi)鏈逐級(jí)搜索,如果找到了函數(shù)對(duì)象這個(gè)方法引用就是合法的。

派生類(lèi)可能會(huì)覆蓋其基類(lèi)的方法。因?yàn)榉椒ㄕ{(diào)用同一個(gè)對(duì)象中的其它方法時(shí)沒(méi)有特權(quán),基類(lèi)的方法調(diào)用同一個(gè)基類(lèi)的方法時(shí),可能實(shí)際上最終調(diào)用了派生類(lèi)中的覆蓋方法。(對(duì)于 C++ 程序員來(lái)說(shuō),Python 中的所有方法本質(zhì)上都是 虛 方法。)

派生類(lèi)中的覆蓋方法可能是想要擴(kuò)充而不是簡(jiǎn)單的替代基類(lèi)中的重名方法。有一個(gè)簡(jiǎn)單的方法可以直接調(diào)用基類(lèi)方法,只要調(diào)用: BaseClassName.methodname(self, arguments)。有時(shí)這對(duì)于客戶(hù)也很有用。(要注意只有 BaseClassName 在同一全局作用域定義或?qū)霑r(shí)才能這樣用。)

Python 有兩個(gè)用于繼承的函數(shù):

函數(shù) isinstance() 用于檢查實(shí)例類(lèi)型: isinstance(obj, int) 只有在 obj.__class__ 是 int 或其它從 int 繼承的類(lèi)型

函數(shù) issubclass() 用于檢查類(lèi)繼承: issubclass(bool, int) 為 True,因?yàn)?bool 是 int 的子類(lèi)。

然而, issubclass(float, int) 為 False,因?yàn)?float 不是 int 的子類(lèi)。

分享名稱(chēng):python函數(shù)繼承系列 python 繼承方法
URL網(wǎng)址:http://muchs.cn/article0/doeipio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、Google、動(dòng)態(tài)網(wǎng)站、ChatGPTApp設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)