日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

面向对象之三大特性:继承,封装,多态

發(fā)布時(shí)間:2023/12/13 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面向对象之三大特性:继承,封装,多态 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

python面向?qū)ο蟮娜筇匦?#xff1a;繼承,封裝,多態(tài)。

1. 封裝:?把很多數(shù)據(jù)封裝到?個(gè)對(duì)象中. 把固定功能的代碼封裝到?個(gè)代碼塊, 函數(shù), 對(duì)象, 打包成模塊. 這都屬于封裝的思想. 具體的情況具體分析. 比如. 你寫了?個(gè)很?B的函數(shù). 那這個(gè)也可以被稱為封裝. 在?向?qū)ο笏枷胫? 是把?些看似?關(guān)緊要的內(nèi)容組合到?起統(tǒng)?進(jìn)?存儲(chǔ)和使?. 這就是封裝.?

2. 繼承:??類可以?動(dòng)擁有?類中除了私有屬性外的其他所有內(nèi)容. 說(shuō)?了, ??可以隨便?爹的東?. 但是朋友們, ?定要認(rèn)清楚?個(gè)事情. 必須先有爹, 后有??. 順序不能亂, 在python中實(shí)現(xiàn)繼承非常簡(jiǎn)單. 在聲明類的時(shí)候, 在類名后?添加?個(gè)?括號(hào),就可以完成繼承關(guān)系. 那么什么情況可以使?繼承呢? 單純的從代碼層?上來(lái)看. 兩個(gè)類具有相同的功能或者特征的時(shí)候. 可以采?繼承的形式. 提取?個(gè)?類, 這個(gè)?類中編寫著兩個(gè)類相同的部分. 然后兩個(gè)類分別取繼承這個(gè)類就可以了. 這樣寫的好處是我們可以避免寫很多重復(fù)的功能和代碼. 如果從語(yǔ)義中去分析的話. 會(huì)簡(jiǎn)單很多. 如果語(yǔ)境中出現(xiàn)了x是?種y. 這時(shí), y是?種泛化的概念. x比y更加具體. 那這時(shí)x就是y的?類. 比如. 貓是?種動(dòng)物. 貓繼承動(dòng)物. 動(dòng)物能動(dòng). 貓也能動(dòng). 這時(shí)貓?jiān)趧?chuàng)建的時(shí)候就有了動(dòng)物的"動(dòng)"這個(gè)屬性. 再比如, ?骨精是?個(gè)妖怪. 妖怪天?就有?個(gè)比較不好的功能叫"吃?", ?骨精?出?就知道如何"吃?". 此時(shí) ?骨精繼承妖精.

3. 多態(tài):?同?個(gè)對(duì)象, 多種形態(tài). 這個(gè)在python中其實(shí)是很不容易說(shuō)明?的. 因?yàn)槲覀?直在?. 只是沒(méi)有具體的說(shuō). 比如. 我們創(chuàng)建?個(gè)變量a = 10 , 我們知道此時(shí)a是整數(shù)類型. 但是我們可以通過(guò)程序讓a = "alex", 這時(shí), a?變成了字符串類型. 這是我們都知道的. 但是, 我要告訴你的是. 這個(gè)就是多態(tài)性. 同?個(gè)變量a可以是多種形態(tài)。

一? 封裝? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

封裝,顧名思義就是將內(nèi)容封裝到某個(gè)地方,以后再去調(diào)用被封裝在某處的內(nèi)容。

所以,在使用面向?qū)ο蟮姆庋b特性時(shí),需要:

  • 將內(nèi)容封裝到某處
  • 從某處調(diào)用被封裝的內(nèi)容

第一步:將內(nèi)容封裝到某處

?self 是一個(gè)形式參數(shù),當(dāng)執(zhí)行 obj1 = Foo('wupeiqi', 18 ) 時(shí),self 等于 obj1

? ? ? ? ? ? ? ? ? ? ? ? ? ? ??當(dāng)執(zhí)行 obj2 = Foo('alex', 78 ) 時(shí),self 等于 obj2

所以,內(nèi)容其實(shí)被封裝到了對(duì)象 obj1 和 obj2 中,每個(gè)對(duì)象中都有 name 和 age 屬性,在內(nèi)存里類似于下圖來(lái)保存。

第二步:從某處調(diào)用被封裝的內(nèi)容

調(diào)用被封裝的內(nèi)容時(shí),有兩種情況:

  • 通過(guò)對(duì)象直接調(diào)用
  • 通過(guò)self間接調(diào)用

1、通過(guò)對(duì)象直接調(diào)用被封裝的內(nèi)容

上圖展示了對(duì)象 obj1 和 obj2 在內(nèi)存中保存的方式,根據(jù)保存格式可以如此調(diào)用被封裝的內(nèi)容:對(duì)象.屬性

class Foo:def __init__(self, name, age):self.name = nameself.age = ageobj1 = Foo('wupeiqi', 18) print obj1.name # 直接調(diào)用obj1對(duì)象的name屬性 print obj1.age # 直接調(diào)用obj1對(duì)象的age屬性 obj2 = Foo('alex', 73) print obj2.name # 直接調(diào)用obj2對(duì)象的name屬性 print obj2.age # 直接調(diào)用obj2對(duì)象的age屬性

2、通過(guò)self間接調(diào)用被封裝的內(nèi)容

執(zhí)行類中的方法時(shí),需要通過(guò)self間接調(diào)用被封裝的內(nèi)容

class Foo:def __init__(self, name, age):self.name = nameself.age = agedef detail(self):print self.nameprint self.ageobj1 = Foo('wupeiqi', 18) obj1.detail() # Python默認(rèn)會(huì)將obj1傳給self參數(shù),即:obj1.detail(obj1),所以,此時(shí)方法內(nèi)部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18 obj2 = Foo('alex', 73) obj2.detail() # Python默認(rèn)會(huì)將obj2傳給self參數(shù),即:obj1.detail(obj2),所以,此時(shí)方法內(nèi)部的 self = obj2,即:self.name 是 alex ; self.age 是 78

綜上所述,對(duì)于面向?qū)ο蟮姆庋b來(lái)說(shuō),其實(shí)就是使用構(gòu)造方法將內(nèi)容封裝到 對(duì)象 中,然后通過(guò)對(duì)象直接或者self間接獲取被封裝的內(nèi)容。

二 多態(tài)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

多態(tài),同一個(gè)對(duì)象,多種形態(tài)。python默認(rèn)支持多態(tài)。

# 在java或者c#定義變量或者給函數(shù)傳值必須定義數(shù)據(jù)類型,否則就報(bào)錯(cuò)。def func(int a):print('a必須是數(shù)字')# 而類似于python這種弱定義類語(yǔ)言,a可以是任意形態(tài)(str,int,object等等)。 def func(a):print('a是什么都可以')# 再比如: class F1:passclass S1(F1):def show(self):print 'S1.show'class S2(F1):def show(self):print 'S2.show'# 由于在Java或C#中定義函數(shù)參數(shù)時(shí),必須指定參數(shù)的類型 # 為了讓Func函數(shù)既可以執(zhí)行S1對(duì)象的show方法,又可以執(zhí)行S2對(duì)象的show方法,所以,定義了一個(gè)S1和S2類的父類 # 而實(shí)際傳入的參數(shù)是:S1對(duì)象和S2對(duì)象def Func(F1 obj): """Func函數(shù)需要接收一個(gè)F1類型或者F1子類的類型"""print obj.show()s1_obj = S1() Func(s1_obj) # 在Func函數(shù)中傳入S1類的對(duì)象 s1_obj,執(zhí)行 S1 的show方法,結(jié)果:S1.show s2_obj = S2() Func(s2_obj) # 在Func函數(shù)中傳入Ss類的對(duì)象 ss_obj,執(zhí)行 Ss 的show方法,結(jié)果:S2.show Python偽代碼實(shí)現(xiàn)Java或C # 的多態(tài) 多態(tài)舉例 python中有一句諺語(yǔ)說(shuō)的好,你看起來(lái)像鴨子,那么你就是鴨子。 對(duì)于代碼上的解釋其實(shí)很簡(jiǎn)答: class A:def f1(self):print('in A f1')def f2(self):print('in A f2')class B:def f1(self):print('in A f1')def f2(self):print('in A f2')obj = A() obj.f1() obj.f2()obj2 = B() obj2.f1() obj2.f2() # A 和 B兩個(gè)類完全沒(méi)有耦合性,但是在某種意義上他們卻統(tǒng)一了一個(gè)標(biāo)準(zhǔn)。 # 對(duì)相同的功能設(shè)定了相同的名字,這樣方便開(kāi)發(fā),這兩個(gè)方法就可以互成為鴨子類型。# 這樣的例子比比皆是:str tuple list 都有 index方法,這就是統(tǒng)一了規(guī)范。 # str bytes 等等 這就是互稱為鴨子類型。 鴨子類型

三 類的約束? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

?先, 你要清楚. 約束是對(duì)類的約束.?

用一個(gè)例子說(shuō)話:

公司讓小明給他們的網(wǎng)站完善一個(gè)支付功能,小明寫了兩個(gè)類,如下:

class QQpay:def pay(self,money):print('使用qq支付%s元' % money)class Alipay:def pay(self,money):print('使用阿里支付%s元' % money)a = Alipay() a.pay(100)b = QQpay() b.pay(200)

但是上面這樣寫不太放方便,也不合理,老大說(shuō)讓他整改,統(tǒng)一一下付款的方式,小明開(kāi)始加班整理:

class QQpay:def pay(self,money):print('使用qq支付%s元' % money)class Alipay:def pay(self,money):print('使用阿里支付%s元' % money)def pay(obj,money): # 這個(gè)函數(shù)就是統(tǒng)一支付規(guī)則,這個(gè)叫做: 歸一化設(shè)計(jì)。 obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)

寫了半年的接口,小明終于接了大項(xiàng)目了,結(jié)果公司沒(méi)品位,招了一個(gè)野生的程序員春哥接替小明的工作,老大給春哥安排了任務(wù),讓他寫一個(gè)微信支付的功能:

class QQpay:def pay(self,money):print('使用qq支付%s元' % money)class Alipay:def pay(self,money):print('使用阿里支付%s元' % money)class Wechatpay: # 野生程序員一般不會(huì)看別人怎么寫,自己才是最好,結(jié)果......def fuqian(self,money):print('使用微信支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)c = Wechatpay() c.fuqian(300)

結(jié)果春哥,受懲罰了,限期整改,那么春哥,發(fā)奮圖強(qiáng),看了太白教你學(xué)python的相關(guān)資料,重新梳理的代碼:

class Payment: """ 此類什么都不做,就是制定一個(gè)標(biāo)準(zhǔn),誰(shuí)繼承我,必須定義我里面的方法。"""def pay(self,money):passclass QQpay(Payment):def pay(self,money):print('使用qq支付%s元' % money)class Alipay(Payment):def pay(self,money):print('使用阿里支付%s元' % money)class Wechatpay(Payment):def fuqian(self,money):print('使用微信支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)c = Wechatpay() c.fuqian(300)

但是,這樣還會(huì)有問(wèn)題,如果再來(lái)野生程序員,他不看其他的支付方式,也不知道為什么繼承的類中要定義一個(gè)沒(méi)有意義的方法,所以他會(huì)是會(huì)我行我素:

class Payment: """ 此類什么都不做,就是制定一個(gè)標(biāo)準(zhǔn),誰(shuí)繼承我,必須定義我里面的方法。"""def pay(self,money):passclass QQpay(Payment):def pay(self,money):print('使用qq支付%s元' % money)class Alipay(Payment):def pay(self,money):print('使用阿里支付%s元' % money)class Wechatpay(Payment):def fuqian(self,money):print('使用微信支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay()pay(a,100) pay(b,200)c = Wechatpay() c.fuqian(300)

所以此時(shí)我們要用到對(duì)類的約束,對(duì)類的約束有兩種:

1. 提取?類. 然后在?類中定義好?法. 在這個(gè)?法中什么都不??. 就拋?個(gè)異常就可以了. 這樣所有的?類都必須重寫這個(gè)?法. 否則. 訪問(wèn)的時(shí)候就會(huì)報(bào)錯(cuò).?

2. 使?元類來(lái)描述?類. 在元類中給出?個(gè)抽象?法. 這樣?類就不得不給出抽象?法的具體實(shí)現(xiàn). 也可以起到約束的效果.

先用第一種方式解決:

class Payment:"""此類什么都不做,就是制定一個(gè)標(biāo)準(zhǔn),誰(shuí)繼承我,必須定義我里面的方法。"""def pay(self,money):raise Exception("你沒(méi)有實(shí)現(xiàn)pay方法")class QQpay(Payment):def pay(self,money):print('使用qq支付%s元' % money)class Alipay(Payment):def pay(self,money):print('使用阿里支付%s元' % money)class Wechatpay(Payment):def fuqian(self,money):print('使用微信支付%s元' % money)def pay(obj,money):obj.pay(money)a = Alipay() b = QQpay() c = Wechatpay() pay(a,100) pay(b,200) pay(c,300)

第二種方式:引入抽象類的概念處理。

from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 抽象類 接口類 規(guī)范和約束 metaclass指定的是一個(gè)元類 @abstractmethoddef pay(self):pass # 抽象方法class Alipay(Payment):def pay(self,money):print('使用支付寶支付了%s元'%money)class QQpay(Payment):def pay(self,money):print('使用qq支付了%s元'%money)class Wechatpay(Payment):# def pay(self,money):# print('使用微信支付了%s元'%money)def recharge(self):passdef pay(a,money):a.pay(money)a = Alipay() a.pay(100) pay(a,100) # 歸一化設(shè)計(jì):不管是哪一個(gè)類的對(duì)象,都調(diào)用同一個(gè)函數(shù)去完成相似的功能 q = QQpay() q.pay(100) pay(q,100) w = Wechatpay() pay(w,100) # 到用的時(shí)候才會(huì)報(bào)錯(cuò)# 抽象類和接口類做的事情 :建立規(guī)范 # 制定一個(gè)類的metaclass是ABCMeta, # 那么這個(gè)類就變成了一個(gè)抽象類(接口類) # 這個(gè)類的主要功能就是建立一個(gè)規(guī)范

總結(jié): 約束. 其實(shí)就是?類對(duì)?類進(jìn)?約束. ?類必須要寫xxx?法. 在python中約束的?式和?法有兩種:

1. 使?抽象類和抽象?法, 由于該?案來(lái)源是java和c#. 所以使?頻率還是很少的

2. 使??為拋出異常的?案. 并且盡量拋出的是NotImplementError. 這樣比較專業(yè), ?且錯(cuò)誤比較明確.(推薦)

四. super()深入了解? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

super是嚴(yán)格按照類的繼承順序執(zhí)行!!!?

class A:def f1(self):print('in A f1')def f2(self):print('in A f2')class Foo(A):def f1(self):super().f2()print('in A Foo')obj = Foo() obj.f1() super可以下一個(gè)類的其他方法 class A:def f1(self):print('in A')class Foo(A):def f1(self):super().f1()print('in Foo')class Bar(A):def f1(self):print('in Bar')class Info(Foo,Bar):def f1(self):super().f1()print('in Info f1')obj = Info() obj.f1()''' in Bar in Foo in Info f1 ''' print(Info.mro()) # [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>] super()嚴(yán)格按照類的mro順序執(zhí)行 class A:def f1(self):print('in A')class Foo(A):def f1(self):super().f1()print('in Foo')class Bar(A):def f1(self):print('in Bar')class Info(Foo,Bar):def f1(self):super(Foo,self).f1()print('in Info f1')obj = Info() obj.f1() 再來(lái)

抽象類? ? ? ?

什么是抽象類

? ? 與java一樣,python也有抽象類的概念但是同樣需要借助模塊實(shí)現(xiàn),抽象類是一個(gè)特殊的類,它的特殊之處在于只能被繼承,不能被實(shí)例化

為什么要有抽象類

??? 如果說(shuō)類是從一堆對(duì)象中抽取相同的內(nèi)容而來(lái)的,那么抽象類是從一堆中抽取相同的內(nèi)容而來(lái)的,內(nèi)容包括數(shù)據(jù)屬性和函數(shù)屬性。

  比如我們有香蕉的類,有蘋果的類,有桃子的類,從這些類抽取相同的內(nèi)容就是水果這個(gè)抽象的類,你吃水果時(shí),要么是吃一個(gè)具體的香蕉,要么是吃一個(gè)具體的桃子。。。。。。你永遠(yuǎn)無(wú)法吃到一個(gè)叫做水果的東西。

? ? 從設(shè)計(jì)角度去看,如果類是從現(xiàn)實(shí)對(duì)象抽象而來(lái)的,那么抽象類就是基于類抽象而來(lái)的。

  從實(shí)現(xiàn)角度來(lái)看,抽象類與普通類的不同之處在于:抽象類中有抽象方法,該類不能被實(shí)例化,只能被繼承,且子類必須實(shí)現(xiàn)抽象方法。這一點(diǎn)與接口有點(diǎn)類似,但其實(shí)是不同的,即將揭曉答案

在python中實(shí)現(xiàn)抽象類

#一切皆文件 import abc #利用abc模塊實(shí)現(xiàn)抽象類class All_file(metaclass=abc.ABCMeta):all_type='file'@abc.abstractmethod #定義抽象方法,無(wú)需實(shí)現(xiàn)功能def read(self):'子類必須定義讀功能'pass@abc.abstractmethod #定義抽象方法,無(wú)需實(shí)現(xiàn)功能def write(self):'子類必須定義寫功能'pass# class Txt(All_file): # pass # # t1=Txt() #報(bào)錯(cuò),子類沒(méi)有定義抽象方法class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('文本數(shù)據(jù)的讀取方法')def write(self):print('文本數(shù)據(jù)的讀取方法')class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('硬盤數(shù)據(jù)的讀取方法')def write(self):print('硬盤數(shù)據(jù)的讀取方法')class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('進(jìn)程數(shù)據(jù)的讀取方法')def write(self):print('進(jìn)程數(shù)據(jù)的讀取方法')wenbenwenjian=Txt()yingpanwenjian=Sata()jinchengwenjian=Process()#這樣大家都是被歸一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read()print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type) View Code

抽象類與接口類

抽象類的本質(zhì)還是類,指的是一組類的相似性,包括數(shù)據(jù)屬性(如all_type)和函數(shù)屬性(如read、write),而接口只強(qiáng)調(diào)函數(shù)屬性的相似性。

抽象類是一個(gè)介于類和接口直接的一個(gè)概念,同時(shí)具備類和接口的部分特性,可以用來(lái)實(shí)現(xiàn)歸一化設(shè)計(jì)?

在python中,并沒(méi)有接口類這種東西,即便不通過(guò)專門的模塊定義接口,我們也應(yīng)該有一些基本的概念。

1.多繼承問(wèn)題

在繼承抽象類的過(guò)程中,我們應(yīng)該盡量避免多繼承;
而在繼承接口的時(shí)候,我們反而鼓勵(lì)你來(lái)多繼承接口

接口隔離原則: 使用多個(gè)專門的接口,而不使用單一的總接口。即客戶端不應(yīng)該依賴那些不需要的接口。

2.方法的實(shí)現(xiàn)

在抽象類中,我們可以對(duì)一些抽象方法做出基礎(chǔ)實(shí)現(xiàn);
而在接口類中,任何方法都只是一種規(guī)范,具體的功能需要子類實(shí)現(xiàn)

抽象類與接口類

1.多繼承問(wèn)題 在繼承抽象類的過(guò)程中,我們應(yīng)該盡量避免多繼承; 而在繼承接口的時(shí)候,我們反而鼓勵(lì)你來(lái)多繼承接口2.方法的實(shí)現(xiàn) 在抽象類中,我們可以對(duì)一些抽象方法做出基礎(chǔ)實(shí)現(xiàn); 而在接口類中,任何方法都只是一種規(guī)范,具體的功能需要子類實(shí)現(xiàn)

轉(zhuǎn)載于:https://www.cnblogs.com/ls13691357174/p/10476773.html

總結(jié)

以上是生活随笔為你收集整理的面向对象之三大特性:继承,封装,多态的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。