這篇文章給大家分享的是有關(guān)Python面向?qū)ο笾械睦^承是什么意思的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧。
專(zhuān)注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)莎車(chē)免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了近1000家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。1、什么是繼承?
繼承指的是類(lèi)與類(lèi)之間的關(guān)系,是一種什么是什么的關(guān)系,功能之一就是用來(lái)解決代碼重用問(wèn)題。
繼承是一種創(chuàng)建新類(lèi)的方式,在python中,新建的類(lèi)可以繼承一個(gè)或多個(gè)父類(lèi),父類(lèi)又可稱為基類(lèi)或超類(lèi),新建的類(lèi)稱為派生類(lèi)或子類(lèi),繼承又分為單繼承和多繼承。
class ParentClass1: #定義父類(lèi) pass class ParentClass2: #定義父類(lèi) pass class SubClass1(ParentClass1): #單繼承,基類(lèi)是ParentClass1,派生類(lèi)是SubClass pass class SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號(hào)分隔開(kāi)多個(gè)繼承的類(lèi) pass print(Son1.__bases__) # 查看所有繼承的父類(lèi) print(Son2.__bases__) =============== (,) ( , )
2、繼承與抽象
抽象分成兩個(gè)層次:
1.將奧巴馬和梅西這倆對(duì)象比較像的部分抽取成類(lèi);
2.將人,豬,狗這三個(gè)類(lèi)比較像的部分抽取成父類(lèi)。
抽象最主要的作用是劃分類(lèi)別(可以隔離關(guān)注點(diǎn),降低復(fù)雜度)
繼承:
是基于抽象的結(jié)果,通過(guò)編程語(yǔ)言去實(shí)現(xiàn)它,肯定是先經(jīng)歷抽象這個(gè)過(guò)程,才能通過(guò)繼承的方式去表達(dá)出抽象的結(jié)構(gòu)。
抽象只是分析和設(shè)計(jì)的過(guò)程中,一個(gè)動(dòng)作或者說(shuō)一種技巧,通過(guò)抽象可以得到類(lèi)。
class animal(): # 定義父類(lèi) country = 'china' # 這個(gè)叫類(lèi)的變量 def __init__(self,name,age): self.name=name # 這些又叫數(shù)據(jù)屬性 self.age=age def walk(self): # 類(lèi)的函數(shù),方法,動(dòng)態(tài)屬性 print('%s is walking'%self.name) def say(self): pass class people(animal): # 子類(lèi)繼承父類(lèi) pass class pig(animal): # 子類(lèi)繼承父類(lèi) pass class dog(animal): # 子類(lèi)繼承父類(lèi) pass aobama=people('aobama',60) # 實(shí)例化一個(gè)對(duì)象 print(aobama.name) aobama.walk() =================== aobama aobama is walking
3、派生
1.在父類(lèi)的基礎(chǔ)上產(chǎn)生子類(lèi),產(chǎn)生的子類(lèi)就叫做派生類(lèi)。
2.父類(lèi)里沒(méi)有的方法,在子類(lèi)中有了,這樣的方法就叫做派生方法。
3.父類(lèi)里有,子類(lèi)也有的方法,就叫做方法的重寫(xiě)(就是把父類(lèi)里的方法重寫(xiě)了)。
例1
class Hero: def __init__(self, nickname, aggressivity, life_value): self.nickname = nickname self.aggressivity = aggressivity self.life_value = life_value def attack(self, enemy): enemy.life_value -= self.aggressivity class Garen(Hero): # 子類(lèi)繼承 hero 父類(lèi) camp='Demacia' # 子類(lèi)衍生出的變量 def attack(self, enemy): ?!「割?lèi)的 attack 重名,對(duì)象調(diào)用的時(shí)候以子類(lèi)的為準(zhǔn) pass def fire(self): # 父類(lèi)沒(méi)有 fire,這里 fire 屬于派生出來(lái)的東西 print('%s is firing' %self.nickname) class Riven(Hero): camp='Noxus' g1=Garen('garen',18,200) r1=Riven('rivren',18,200) # print(g1.camp) # print(r1.camp) # g1.fire() g1.attack(g1)
例2
class Hero: def __init__(self, nickname,aggressivity,life_value): self.nickname = nickname self.aggressivity = aggressivity self.life_value = life_value def attack(self, enemy): print('Hero attack') class Garen(Hero): camp = 'Demacia' def attack(self, enemy): #self=g1,enemy=r1 # self.attack(enemy) #g1.attack(r1),這里相當(dāng)于無(wú)限遞歸 Hero.attack(self,enemy) # 引用 父類(lèi)的 attack,對(duì)象會(huì)去跑 父類(lèi)的 attack print('from garen attack') # 再回來(lái)這里 def fire(self): print('%s is firing' % self.nickname) class Riven(Hero): camp = 'Noxus' g1 = Garen('garen', 18, 200) r1 = Riven('rivren', 18, 200) g1.attack(r1) # print(g1.camp) # print(r1.camp) # g1.fire()
4、組合與重用性
重用性:
方式1:不通過(guò)繼承的方式重用屬性,指名道姓的使用哪個(gè)類(lèi)的屬性。
class Hero: def __init__(self,nickname,gongji,life): self.nickname=nickname self.gongji=gongji self.life=life def attack(self,obj): print('from Hero attack') class Garen: def __init__(self,nickname,gongji,life,script): Hero.__init__(self,nickname,gongji,life) # 這里引用Hero類(lèi)的 init,不用再自己從新定義一遍 init self.script=script # 父類(lèi) init 沒(méi)有 script,這里是新加進(jìn)來(lái)的屬性 def attack(self,obj): # 在這里自己定義新的 attack,不再使用父類(lèi)的 attack print('from Garen attack') def fire(self): # 在這里定義新的功能 print('from Garen fire') g1=Garen('garen',18,200,'人在塔在') print(g1.script) 人在塔在
提示:用已經(jīng)有的類(lèi)建立一個(gè)新的類(lèi),這樣就重用了已經(jīng)有的軟件中的一部分甚至大部分,大大省了編程工作量,這就是常說(shuō)的軟件重用,不僅可以重用自己的類(lèi),也可以繼承別人的,比如標(biāo)準(zhǔn)庫(kù),來(lái)定制新的數(shù)據(jù)類(lèi)型,這樣就是大大縮短了軟件開(kāi)發(fā)周期,對(duì)大型軟件開(kāi)發(fā)來(lái)說(shuō),意義重大。
注意:像g1.life之類(lèi)的屬性引用,會(huì)先從實(shí)例中找life,然后去類(lèi)中找,然后再去父類(lèi)中找...直到最頂級(jí)的父類(lèi)。
方式2:通過(guò)繼承
例1
class Hero(): def __init__(self, nickname, gongji, life): self.nickname = nickname self.gongji = gongji self.life = life def attack(self, obj): print('from Hero attack') obj.life -= self.gongji class Garen(Hero): # 使用 super方式需要繼承 camp = 'Demacia' def __init__(self, nickname, gongji, life): super().__init__(nickname, gongji, life) def attack(self, obj): # 在這里自己定義新的 attack,不再使用父類(lèi)的 attack super(Garen, self).attack(obj) # PY3中super可以不給參數(shù),PY2中第一個(gè)參數(shù)必須是自己的類(lèi),self,可以使用 父類(lèi)的方法,方法需要給參數(shù)就給參數(shù) def fire(self): # 在這里定義新的功能 print('from Garen fire') g1 = Garen('garen1', 18, 200) g2 = Garen('garen2', 20, 100) print(g2.life) g1.attack(g2) print(g2.life) 100 from Hero attack 82
例2
class A: def f1(self): print('from A') super().f1() # 這種不需要繼承也可以使用到 super,為什么,要看 C的 MRO表 class B: def f1(self): print('from B') class C(A,B): pass print(C.mro()) #[, # , # , # B在A的后面,當(dāng)A指定 super().f1 會(huì)找到 B的 f1 # ] c=C() c.f1()
組合:
軟件重用的重要方式除了繼承之外還有另外一種方式,即:組合。
組合:一個(gè)對(duì)象的數(shù)據(jù)屬性是另一個(gè)對(duì)象,稱為組合。
class Equip: #武器裝備類(lèi) def fire(self): print('release Fire skill') class Riven: #英雄Riven的類(lèi),一個(gè)英雄需要有裝備,因而需要組合Equip類(lèi) camp='Noxus' def __init__(self,nickname): self.nickname=nickname self.equip=Equip() #用Equip類(lèi)產(chǎn)生一個(gè)裝備,賦值給實(shí)例的equip屬性 r1=Riven('銳雯雯') r1.equip.fire() #可以使用組合的類(lèi)產(chǎn)生的對(duì)象所持有的方法 release Fire skill
組合的方式:
組合與繼承都是有效地利用已有類(lèi)的資源的重要方式。但是二者的概念和使用場(chǎng)景皆不同。
1.繼承的方式
通過(guò)繼承建立了派生類(lèi)與基類(lèi)之間的關(guān)系,它是一種'是'的關(guān)系,比如白馬是馬,人是動(dòng)物。
當(dāng)類(lèi)之間有很多相同的功能,提取這些共同的功能做成基類(lèi),用繼承比較好,比如老師是人,學(xué)生是人
2.組合的方式
用組合的方式建立了類(lèi)與組合的類(lèi)之間的關(guān)系,它是一種‘有’的關(guān)系,比如教授有生日,教授教python和linux課程,教授有學(xué)生s1、s2、s3...
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class Course: def __init__(self,name,period,price): self.name=name self.period=period self.price=price def tell_info(self): print('<%s %s %s>' %(self.name,self.period,self.price)) class Teacher(People): def __init__(self,name,age,sex,job_title): People.__init__(self,name,age,sex) self.job_title=job_title self.course=[] self.students=[] class Student(People): def __init__(self,name,age,sex): People.__init__(self,name,age,sex) self.course=[] egon=Teacher('egon',18,'male','沙河霸道金牌講師') s1=Student('牛榴彈',18,'female') python=Course('python','3mons',3000.0) linux=Course('python','3mons',3000.0) #為老師egon和學(xué)生s1添加課程 egon.course.append(python) egon.course.append(linux) s1.course.append(python) #為老師egon添加學(xué)生s1 egon.students.append(s1) #使用 for obj in egon.course: obj.tell_info()
5、接口與歸一化設(shè)計(jì)
a、為何要用接口?
接口提取了一群類(lèi)共同的函數(shù),可以把接口當(dāng)做一個(gè)函數(shù)的集合。
然后讓子類(lèi)去實(shí)現(xiàn)接口中的函數(shù)。
這么做的意義在于歸一化,什么叫歸一化,就是只要是基于同一個(gè)接口實(shí)現(xiàn)的類(lèi),那么所有的這些類(lèi)產(chǎn)生的對(duì)象在使用時(shí),從用法上來(lái)說(shuō)都一樣。
歸一化的好處在于:
歸一化讓使用者無(wú)需關(guān)心對(duì)象的類(lèi)是什么,只需要的知道這些對(duì)象都具備某些功能就可以了,這極大地降低了使用者的使用難度。
class Interface:#定義接口Interface類(lèi)來(lái)模仿接口的概念,python中壓根就沒(méi)有interface關(guān)鍵字來(lái)定義一個(gè)接口。 def read(self): #定接口函數(shù)read pass def write(self): #定義接口函數(shù)write pass class Txt(Interface): #文本,具體實(shí)現(xiàn)read和write def read(self): print('文本數(shù)據(jù)的讀取方法') def write(self): print('文本數(shù)據(jù)的讀取方法') class Sata(Interface): #磁盤(pán),具體實(shí)現(xiàn)read和write def read(self): print('硬盤(pán)數(shù)據(jù)的讀取方法') def write(self): print('硬盤(pán)數(shù)據(jù)的讀取方法') class Process(Interface): def read(self): print('進(jìn)程數(shù)據(jù)的讀取方法') def write(self): print('進(jìn)程數(shù)據(jù)的讀取方法')
上面的代碼只是看起來(lái)像接口,其實(shí)并沒(méi)有起到接口的作用,子類(lèi)完全可以不用去實(shí)現(xiàn)接口,這就用到了抽象類(lèi)。
6、抽象類(lèi)
子類(lèi)必須繼承抽象類(lèi)的方法,不然報(bào)錯(cuò)。
什么是抽象類(lèi)?
與java一樣,python也有抽象類(lèi)的概念但是同樣需要借助模塊實(shí)現(xiàn),抽象類(lèi)是一個(gè)特殊的類(lèi),它的特殊之處在于只能被繼承,不能被實(shí)例化
為什么要有抽象類(lèi)?
如果說(shuō)類(lèi)是從一堆對(duì)象中抽取相同的內(nèi)容而來(lái)的,那么抽象類(lèi)就是從一堆類(lèi)中抽取相同的內(nèi)容而來(lái)的,內(nèi)容包括數(shù)據(jù)屬性和函數(shù)屬性。
比如我們有香蕉的類(lèi),有蘋(píng)果的類(lèi),有桃子的類(lèi),從這些類(lèi)抽取相同的內(nèi)容就是水果這個(gè)抽象的類(lèi),你吃水果時(shí),要么是吃一個(gè)具體的香蕉,要么是吃一個(gè)具體的桃子。你永遠(yuǎn)無(wú)法吃到一個(gè)叫做水果的東西。
從設(shè)計(jì)角度去看,如果類(lèi)是從現(xiàn)實(shí)對(duì)象抽象而來(lái)的,那么抽象類(lèi)就是基于類(lèi)抽象而來(lái)的。
從實(shí)現(xiàn)角度來(lái)看,抽象類(lèi)與普通類(lèi)的不同之處在于:抽象類(lèi)中只能有抽象方法(沒(méi)有實(shí)現(xiàn)功能),該類(lèi)不能被實(shí)例化,只能被繼承,且子類(lèi)必須實(shí)現(xiàn)抽象方法。
抽象類(lèi)與接口
抽象類(lèi)的本質(zhì)還是類(lèi),指的是一組類(lèi)的相似性,包括數(shù)據(jù)屬性(如all_type)和函數(shù)屬性(如read、write),而接口只強(qiáng)調(diào)函數(shù)屬性的相似性。
抽象類(lèi)是一個(gè)介于類(lèi)和接口直接的一個(gè)概念,同時(shí)具備類(lèi)和接口的部分特性,可以用來(lái)實(shí)現(xiàn)歸一化設(shè)計(jì)。
例1
import abc #抽象類(lèi):本質(zhì)還是類(lèi),與普通類(lèi)額外的特點(diǎn)的是:加了裝飾器的函數(shù),子類(lèi)必須實(shí)現(xiàn)他們 class Animal(metaclass=abc.ABCMeta): # 抽象類(lèi)是用來(lái)被子類(lèi)繼承的,不是用來(lái)實(shí)例化的 tag='123123123123123' @abc.abstractmethod # 如果子類(lèi)沒(méi)有我這個(gè)函數(shù),主動(dòng)拋出異常 def run(self): pass @abc.abstractmethod def speak(self): pass class People(Animal): def run(self): # 子類(lèi)必須有抽象類(lèi)里的裝飾器下面的函數(shù) pass def speak(self): pass peo1=People() # 實(shí)例化出來(lái)一個(gè)人 print(peo1.tag)
例2
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' #一切皆文件 import abc #利用abc模塊實(shí)現(xiàn)抽象類(lèi) class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定義抽象方法,無(wú)需實(shí)現(xiàn)功能 def read(self): '子類(lèi)必須定義讀功能' pass @abc.abstractmethod #定義抽象方法,無(wú)需實(shí)現(xiàn)功能 def write(self): '子類(lèi)必須定義寫(xiě)功能' pass # class Txt(All_file): # pass # # t1=Txt() #報(bào)錯(cuò),子類(lèi)沒(méi)有定義抽象方法 class Txt(All_file): #子類(lèi)繼承抽象類(lèi),但是必須定義read和write方法 def read(self): print('文本數(shù)據(jù)的讀取方法') def write(self): print('文本數(shù)據(jù)的讀取方法') class Sata(All_file): #子類(lèi)繼承抽象類(lèi),但是必須定義read和write方法 def read(self): print('硬盤(pán)數(shù)據(jù)的讀取方法') def write(self): print('硬盤(pán)數(shù)據(jù)的讀取方法') class Process(All_file): #子類(lèi)繼承抽象類(lèi),但是必須定義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)
感謝各位的閱讀!關(guān)于Python面向?qū)ο笾械睦^承是什么意思就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!