欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python面向?qū)ο笕筇卣鳎豪^承、封裝和多態(tài)的深度解析

 更新時(shí)間:2025年01月11日 09:31:08   作者:小劉042  
在面向?qū)ο蟪绦蛟O(shè)計(jì)中,對(duì)象可以看做是數(shù)據(jù)(特性)以及由一系列可以存取、操作這些數(shù)據(jù)的方法所組成的集合,Python是面向?qū)ο蟮恼Z(yǔ)言,支持面向?qū)ο缶幊痰娜筇匦裕豪^承、封裝(隱藏)、多態(tài),本文將逐一講解Python的三大特性

在面向?qū)ο蟪绦蛟O(shè)計(jì)中,對(duì)象可以看做是數(shù)據(jù)(特性)以及由一系列可以存取、操作這些數(shù)據(jù)的方法所組成的集合。Python是面向?qū)ο蟮恼Z(yǔ)言,支持面向?qū)ο缶幊痰娜筇匦裕豪^承、封裝(隱藏)、多態(tài),本文將逐一講解Python的三大特性。

封裝

繼承的基本概念以及使用

封裝的概念:隱藏內(nèi)部實(shí)現(xiàn)的細(xì)節(jié),只對(duì)外提供操作方法(接口)。這個(gè)概念我們?cè)谏弦恍」?jié)中也已經(jīng)學(xué)習(xí)過(guò)了,我們主要是去了解其在代碼中是如何去實(shí)現(xiàn)的:通過(guò)有著類(lèi)似 訪(fǎng)問(wèn)修飾限定符 功能的下劃線(xiàn)來(lái)實(shí)現(xiàn)。

權(quán)限控制:通過(guò)對(duì)屬性或方法添加單下劃線(xiàn)、雙下劃線(xiàn)以及首尾雙下劃線(xiàn)來(lái)實(shí)現(xiàn)。

下劃線(xiàn)種類(lèi)

功能

單下劃線(xiàn)開(kāi)頭

表示protected,受保護(hù)的成員,這類(lèi)成員被視為僅供內(nèi)部家族使用,允許類(lèi)本身和子類(lèi)進(jìn)行訪(fǎng)問(wèn),但實(shí)際上它可以被外部代碼訪(fǎng)問(wèn)

雙下劃線(xiàn)開(kāi)頭

表示private,私有的成員,這類(lèi)成員只允許定義該屬性或方法的類(lèi)本身進(jìn)行訪(fǎng)問(wèn)

首尾雙下劃線(xiàn)

一般表示特殊的方法

代碼演示:

class Dog():
    # 首尾雙線(xiàn)劃線(xiàn) ——> 特殊方法
    def __init__(self, name, age):
        # 雙下劃線(xiàn)開(kāi)頭 ——> private修飾,只能在類(lèi)內(nèi)訪(fǎng)問(wèn)
        self.__name = name
        # 單下劃線(xiàn)開(kāi)頭 ——> protected修飾,在類(lèi)內(nèi)與子類(lèi)才能訪(fǎng)問(wèn)
        self._age = age
 
    # 單下劃線(xiàn)開(kāi)頭 ——> protected修飾,在類(lèi)內(nèi)與子類(lèi)才能訪(fǎng)問(wèn)
    def _fun1(self):
        print('這是被protected所修飾的方法')
    # 雙下劃線(xiàn)開(kāi)頭 ——> private修飾,在類(lèi)內(nèi)才能訪(fǎng)問(wèn)
    def __fun2(self):
        print('這是被private所修飾的方法')
 
# 這里是類(lèi)外了
dog = Dog('小劉', 18)
print(dog._age)
# print(dog.__name)
dog._fun1()
# dog.__fun2()
# 和上面一樣,直接去訪(fǎng)問(wèn)的話(huà),就會(huì)報(bào)錯(cuò),
# 但是我們可以使用 對(duì)象.__dir()__ 或者 dir(對(duì)象) 先去查看所有的屬性與方法
# 然后通過(guò)其中的"屬性"與"方法名"去調(diào)用真正的屬性與方法
# print(dog.__dir__())
# print(dir(dog))
 
print(dog._Dog__name)
dog._Dog__fun2()

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

Python初始 - 面向?qū)ο笕筇卣鱛下劃線(xiàn)

根據(jù)上面的訪(fǎng)問(wèn)方式,我們可以推測(cè)出:被 protected、private 所修飾 方法 與 屬性只是在類(lèi)中對(duì)應(yīng)的名稱(chēng)發(fā)生了變化,而我們不知道,但是可以通過(guò)特殊手段知曉,從而繼續(xù)訪(fǎng)問(wèn)。

但是上面的方式不是很推薦,類(lèi)似與 Java中的反射機(jī)制了,有點(diǎn)反常規(guī)。除了上面這種方式,Python還提供了兩種方式來(lái)實(shí)現(xiàn)訪(fǎng)問(wèn) 與 修改 私有是屬性與方法。

1、在 私有的方法 或者 屬性上,進(jìn)行套殼處理。

2、在1的基礎(chǔ)上,通過(guò) @property 裝飾器 來(lái)修飾方法,使其變?yōu)閷傩裕妥優(yōu)樵L(fǎng)問(wèn)與修改屬性了,最終也會(huì)變的很簡(jiǎn)單。

代碼演示:

class Dog():
    def __init__(self, name, age):
        self.__name = name
        self.age = age
 
    # 如果想要去訪(fǎng)問(wèn)除了,使用dir()之外,還有兩種方式:
 
    # 使用實(shí)例方法去間接訪(fǎng)問(wèn)與修改
    def get_name(self):
        return self.__name
    def set_name(self, name):
        self.__name = name
 
    # 使用@property裝飾器,將方法轉(zhuǎn)為屬性使用
    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self, name):
        self.__name = name
 
dog = Dog('老劉', 8)
# 1、通過(guò)實(shí)例方法的形式去使用
print(dog.get_name())
dog.set_name('小劉')
print('='*18)
# 2、通過(guò)@property裝飾器,將方法轉(zhuǎn)為屬性
print(dog.name)
dog.name = '老劉' # 修改屬性的樣式,去傳參
print(dog._Dog__name)
print('='*18)
dog._Dog__name = '小劉'
print(dog._Dog__name)

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

Python初始 - 面向?qū)ο笕筇卣鱛父類(lèi)_02

注意:我們?cè)谑褂?@property 裝飾器,將屬性轉(zhuǎn)為方法時(shí),取值的方法,必須被 @property 修飾,而修改值的方法,必須被 @取值方法名. setter修飾。

繼承

繼承的基本概念以及使用

繼承是指一個(gè)類(lèi)(子類(lèi)、派生類(lèi))繼承另一個(gè)類(lèi)(父類(lèi)、基類(lèi))的屬性與方法。

在Python中一個(gè)子類(lèi)可以繼承N多個(gè)父類(lèi),這是與 Java決然不同的一點(diǎn)。Java屬于單繼承,而Python屬于多繼承,并且每個(gè)類(lèi)都默認(rèn)繼承自object類(lèi)。當(dāng)然,一個(gè)子類(lèi)可以有多個(gè)父類(lèi),一個(gè)父類(lèi)也可以有多個(gè)子類(lèi)。

語(yǔ)法:

class 類(lèi)名([父類(lèi)列表]):

注意:當(dāng)一個(gè)類(lèi)的父類(lèi)只有object類(lèi)時(shí),默認(rèn)是可以不寫(xiě)父類(lèi)的,但是如果一個(gè)類(lèi)有除object類(lèi)之外的其他類(lèi),就需要將這些類(lèi)全部寫(xiě)到 () 中,當(dāng)然這個(gè)()在只有繼承object類(lèi)的情況下,也是可以不寫(xiě)的,但是建議還是要寫(xiě)上去。

代碼演示:

# 默認(rèn)繼承object類(lèi),但是這個(gè)可以不寫(xiě)
class Animal(object):
    def __init__(self, name, age, gender,sort):
        self.name = name
        self.age = age
        self.gender = gender
        self.__sort = sort
 
 
class Dog(Animal):
    pass
 
# 子類(lèi)繼承父類(lèi),會(huì)將父類(lèi)中除private修飾的方法與屬性全部拿過(guò)來(lái)
# 繼承了 __init__方法,以及 name、age、gender屬性
dog = Dog('小黑', 3, '雄', '哈士奇')
print(dog.name)
print(dog.age)
print(dog.gender)
# 同樣需要特殊手段才能訪(fǎng)問(wèn)到
print(dog._Animal__sort)

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

Python初始 - 面向?qū)ο笕筇卣鱛子類(lèi)_03

注意:我們?cè)趯?shí)例化一個(gè)對(duì)象時(shí),會(huì)先去調(diào)用構(gòu)造方法(init 方法)給對(duì)象的屬性進(jìn)行初始化賦值,如果一個(gè)類(lèi)沒(méi)有構(gòu)造方法,但是由于這個(gè)類(lèi)是默認(rèn)繼承自object類(lèi),因此會(huì)調(diào)用object類(lèi)中默認(rèn)的 init 方法,但如果這個(gè)類(lèi)繼承了其他類(lèi),就會(huì)先在其他類(lèi)中去搜索這個(gè)方法,如果有則調(diào)用;反之,則還是去調(diào)用object類(lèi)的。 而在上面的代碼中,Animal 類(lèi)是有 init 方法,因此會(huì)去調(diào)用Animal 類(lèi)的。

我們?cè)倏纯炊嗬^承的代碼:

class Person():
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def show(self):
        print(f'我叫{self.name},今年{self.age},性別是{self.gender}')
 
class Father(Person):
    def __init__(self,name,age,gender):
        # 可以直接調(diào)用父類(lèi)的初始化方法
        super().__init__(name,age,gender)
        # 下面這種方式是錯(cuò)誤的
        # super().name = name
        # super().age = age
        # super().gender = gender
        # 下面的方式也行,但是不推薦
        # self.name = name
        # self.age = age
        # self.gender = gender
 
class Mother(Person):
    def __init__(self, name, age, gender):
        # 可以直接調(diào)用父類(lèi)的初始化方法
        super().__init__(name, age, gender)
        # 下面這種方式是錯(cuò)誤的
        # super().name = name
        # super().age = age
        # super().gender = gender
        # 下面的方式也行,但是不推薦
        # self.name = name
        # self.age = age
        # self.gender = gender
 
class Son(Father, Mother):
    def __init__(self, name, age, gender):
        # 可以直接調(diào)用父類(lèi)的初始化方法
        super().__init__(name, age, gender)
        # 下面這種方式是錯(cuò)誤的
        # super().name = name
        # super().age = age
        # super().gender = gender
        # 下面的方式也行,但是不推薦
        # self.name = name
        # self.age = age
        # self.gender = gender
 
father = Father('張三',25,'男')
mother = Mother('紅粉佳人',28,'女')
son = Son('趙四',29,'男')
 
father.show()
mother.show()
son.show()

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

Python初始 - 面向?qū)ο笕筇卣鱛下劃線(xiàn)_04

上面的代碼中,Son類(lèi)、Mother類(lèi)、Father類(lèi)都是繼承自Person類(lèi)的屬性與方法,它們是公用Person類(lèi)的屬性與方法。

注意:上述 Son類(lèi)繼承了多個(gè)父類(lèi),當(dāng)我們?nèi)ナ褂?super().init 方法初始化子類(lèi)對(duì)象時(shí),默認(rèn)是按照父類(lèi)在Son()中的順序來(lái)查找的,這里是Father類(lèi)定義聲明在前,因此這里調(diào)用的就是 Father 類(lèi)的 init 方法,如果想要指定某個(gè)類(lèi)的 init 方法的話(huà),就需要使用 類(lèi)名.init() 方法。例如:

# 這里的self代指當(dāng)前Son類(lèi)的實(shí)例對(duì)象
Mother.__init__(self,name,age,gender) # 可替換Son類(lèi)中是super.init

方法重寫(xiě)

當(dāng)子類(lèi)繼承父類(lèi)時(shí),子類(lèi)就擁有了父類(lèi)中的 公有成員、方法和受保護(hù)的成員、方法。如果我們對(duì)父類(lèi)中有些成員不滿(mǎn)意的話(huà),子類(lèi)就可以重新定義成員。同理,方法也是如此,但是重新定義方法麻煩了,那有什么辦法呢?方法重寫(xiě),即 偷梁換柱,表面上這個(gè)方法還是原來(lái)的方法,但是其內(nèi)部實(shí)現(xiàn)的結(jié)構(gòu)早就發(fā)生變化了。

重寫(xiě)的要求:方法名必須一樣,至于方法的返回值類(lèi)型,參數(shù)列表、訪(fǎng)問(wèn)權(quán)限這些可以不一樣。

代碼演示:

class Animal():
    def __init__(self,name,age):
        self.name = name
        self.age = age
 
    def eat(self):
        print(f'{self.name}正在吃狗糧,看小黑玩飛盤(pán)')
 
class Dog(Animal):
    def __init__(self,name,age):
        super().__init__(name,age)
    # 由于Animal類(lèi)的eat方法只是隨便說(shuō)在吃啥,并不具體,
    # 但我們想要打印出具體的食物,因此可以重寫(xiě)(外殼不變,核心變化)
    def eat(self):
        print(f'{self.name}正在玩飛盤(pán)~')
 
class Cat(Animal):
    def __init__(self,name,age):
        super().__init__(name,age)
 
dog = Dog('小黑', 2)
# 子類(lèi)重寫(xiě)父類(lèi)的方法之后,父類(lèi)再去調(diào)用eat方法,就不再是調(diào)用父類(lèi)的,而是自己的
dog.eat()
 
cat = Cat('小黃', 3)
# 子類(lèi)沒(méi)有重寫(xiě)父類(lèi)的eat方法,因此還是去調(diào)用父類(lèi)的eat方法
cat.eat()

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

Python初始 - 面向?qū)ο笕筇卣鱛父類(lèi)_05

其實(shí),重寫(xiě)就是在子類(lèi)中定義了一個(gè)與父類(lèi)重名的方法,只不過(guò)因?yàn)?Python中語(yǔ)法的檢查不是很?chē)?yán)格,因此這里就很容易不理解。

在Python中,我們就將重寫(xiě)看作是子類(lèi)定義了一個(gè)與父類(lèi)重名的方法即可,在調(diào)用時(shí),如果子類(lèi)沒(méi)有這個(gè)方法,那么就是調(diào)用父類(lèi)的同名方法,如果還沒(méi)有就會(huì)報(bào)錯(cuò)。但如果子類(lèi)有這個(gè)方法,那么就是直接調(diào)用子類(lèi)的方法,即使父類(lèi)有,也不去調(diào)用("地頭蛇原則")。

多態(tài)

多態(tài)的概念以及基本使用

多態(tài)是指多種形態(tài),當(dāng)去完成某個(gè)行為時(shí),不同的對(duì)象可能會(huì)產(chǎn)生不同的形態(tài)。

例如,我們?cè)陬?lèi)和對(duì)象中說(shuō)的小故事:當(dāng)劉建明 與 陳永仁 遇到 韓琛 時(shí),兩人打招呼的方式不一樣,這就是不同對(duì)象 在 完成同一個(gè)行為時(shí),兩者所產(chǎn)生的形態(tài)不同。

再比如,我們每天都會(huì)吃早餐,但是不同的人 在 面對(duì)這件事情時(shí),所表現(xiàn)出的行為就不一樣,A 可能吃面條,B可能吃包子、餃子,C可能吃大米飯等。

Python中的多態(tài)與Java、C++不同,Python中的多態(tài)只需要滿(mǎn)足有該方法,然后讓不同的對(duì)象去調(diào)用即可,而 Java 中的多態(tài)需要滿(mǎn)足三個(gè)條件:向上轉(zhuǎn)型(父類(lèi)引用指向子類(lèi)對(duì)象)、子類(lèi)重寫(xiě)父類(lèi)的方法、向上轉(zhuǎn)型的父類(lèi)調(diào)用該方法(被重寫(xiě)的方法),這時(shí)就不再是調(diào)用父類(lèi)的方法,而是調(diào)用子類(lèi)的方法。但 Python中,只要這兩個(gè)類(lèi)有相同的方法,當(dāng)兩者賦值給同一個(gè)對(duì)象時(shí),去調(diào)用同一個(gè)方法就會(huì)表現(xiàn)出不同的行為。

其實(shí),多態(tài)就是表層對(duì)象一樣,內(nèi)部實(shí)際的對(duì)象不一樣,那么在調(diào)用同一個(gè)方法時(shí),雖然看似是這個(gè)表層的對(duì)象所調(diào)用的,但實(shí)際是內(nèi)部的對(duì)象所調(diào)用并執(zhí)行的。

代碼演示:

class Animal():
    def eat(self):
        print('在玩飛盤(pán)')


class Person():
    def eat(self):
        print('到處溜達(dá)')


class Dog():
    def eat(self):
        print('瘋狂奔跑')


class Cat():
    def eat(self):
        print('偷吃罐頭')


# 定義一個(gè)函數(shù),傳入obj對(duì)象,并調(diào)用該對(duì)象的eat方法
def eat(obj):
    obj.eat()


# 方法得通過(guò)類(lèi)或者對(duì)象去"."調(diào)用,而函數(shù)是直接傳參調(diào)用,不要弄混了
eat(Animal())  # 這里需要傳入對(duì)象,即:類(lèi)名()
eat(Person())
eat(Dog())
eat(Cat())

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

Python初始 - 面向?qū)ο笕筇卣鱛父類(lèi)_06

總結(jié)

到此這篇關(guān)于Python面向?qū)ο笕筇卣鳎豪^承、封裝(隱藏)、多態(tài)的文章就介紹到這了,更多相關(guān)Python面向?qū)ο笕筇卣鲀?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論