版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章類(lèi)Python程序設(shè)計(jì)基礎(chǔ)教程(慕課版)工業(yè)和信息化人才培養(yǎng)規(guī)劃教材國(guó)家精品資源共享課程配套教材高職高專計(jì)算機(jī)系列人民郵電出版社我們已經(jīng)接觸過(guò)多種數(shù)據(jù)類(lèi)型:數(shù)字、字符串、元組、列表、字典等。它們可以用來(lái)描述不同的實(shí)際需要,適用不同的場(chǎng)合,解決不同的問(wèn)題。本章將介紹另一種數(shù)據(jù)類(lèi)型:類(lèi)(class)。本章導(dǎo)讀Thechapter’sintroduction目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.1.1類(lèi)與對(duì)象的概念例如,一說(shuō)到球,人的頭腦中馬上就會(huì)把它想象成一種圓形的物體,它的大小由半徑?jīng)Q定,它的外表可以有不同顏色;對(duì)球施以外力后,它會(huì)往遠(yuǎn)處滾動(dòng),或上下來(lái)回彈跳。但是,我們能真正拿出一個(gè)叫“球”的物體嗎?不可能,世上沒(méi)有一個(gè)東西具體叫作“球”,只有諸如“乒乓球”“籃球”“排球”等,才是實(shí)實(shí)在在的“球”。因此,“球”與“乒乓球”等不是一回事。“球”,是對(duì)諸如“乒乓球”“籃球”“排球”等的一種抽象;而“乒乓球”“籃球”“排球”等,則是對(duì)“球”的一個(gè)個(gè)具體化。“球”是圓的,大小由半徑?jīng)Q定,外表可以有不同顏色,施加外力后會(huì)滾動(dòng)或彈跳,這些抽象的特征和行為,都是從“乒乓球”“籃球”“排球”等里面抽取出來(lái)的;而每一種具體的球,又都必須具有抽取出來(lái)的這些特征和行為。于是,人們把抽象的“球”視為是世間的一種數(shù)據(jù)類(lèi)型——“類(lèi)”;把具體的“乒乓球”“籃球”“排球”等,視為這種類(lèi)的“實(shí)例化”,或者說(shuō)是該類(lèi)的一個(gè)個(gè)“對(duì)象”。6.1.1類(lèi)與對(duì)象的概念可以舉出很多類(lèi)和對(duì)象的例子。例如,“動(dòng)物”是類(lèi),“獅子”“羚羊”“狗”等是動(dòng)物類(lèi)的對(duì)象。但從另一個(gè)角度講,“狗”是一個(gè)類(lèi),“獵狗”“寵物狗”“藏獒”等又是狗這類(lèi)的對(duì)象?!皩櫸锕贰庇挚梢栽偌?xì)化成一個(gè)類(lèi),“京巴狗”“約克夏”“哈士奇”等是寵物狗類(lèi)的對(duì)象。人們就是以這種“分門(mén)別類(lèi)”的辦法,一點(diǎn)點(diǎn)深入,一點(diǎn)點(diǎn)細(xì)化,逐漸對(duì)世間萬(wàn)物進(jìn)行了解、描述和研究。從上面的討論可以得出下面的兩點(diǎn)共識(shí)?!邦?lèi)”是一種抽象的概念,它代表了現(xiàn)實(shí)世界中某些事物的共有特征和行為?!皩?duì)象”是對(duì)類(lèi)的實(shí)例化,每個(gè)對(duì)象都會(huì)自動(dòng)具有所屬類(lèi)的通用特征和行為。當(dāng)然,根據(jù)需要,對(duì)象也可以具有自己獨(dú)特的個(gè)性特征與行為。目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.1.2Python中類(lèi)的定義Python中的類(lèi)是借助關(guān)鍵字class來(lái)定義的。具體語(yǔ)法如下:它由兩大部分組成,以class開(kāi)頭、“:”冒號(hào)結(jié)束的第1行被稱為“類(lèi)頭”,縮進(jìn)的<成員變量>與<成員函數(shù)>被稱為“類(lèi)體”。其中,<類(lèi)名>必須符合Python對(duì)變量取名所做的規(guī)定。進(jìn)一步地,為了便于區(qū)分,Python約定<類(lèi)名>的第1個(gè)字母必須大寫(xiě)。<成員變量>就是類(lèi)的成員屬性,簡(jiǎn)稱“屬性”。<成員變量>包含在描述該類(lèi)成員(也就是對(duì)象)共有的抽象特征時(shí)涉及的各種變量。class<類(lèi)名>():
<成員變量> <成員函數(shù)>6.1.2Python中類(lèi)的定義下面直接舉出3個(gè)Python中類(lèi)的定義的例子,只要了解了前面關(guān)于函數(shù)的那些知識(shí),那么大致理解例子中所要描述的內(nèi)容便不會(huì)有太大的難度。<成員函數(shù)>即成員方法,簡(jiǎn)稱“方法”。<成員函數(shù)>包含描述該類(lèi)成員(也就是對(duì)象)所具有的抽象行為或動(dòng)作的各種函數(shù)。在一個(gè)“類(lèi)”的定義里,<成員變量>和<成員函數(shù)>當(dāng)然可以不止一個(gè)。classDog():#定義類(lèi)Dog def__init__(self,name,age): =name self.age=age defsit(self): print(.title()+'isnowsitting.') defr_over(self): print(.title()+'rolledover!')例6-1定義一個(gè)“狗”類(lèi):6.1.2Python中類(lèi)的定義該類(lèi)的名字是Dog,它的首字母為大寫(xiě),符合Python對(duì)類(lèi)的定義所做的約定要求。在縮進(jìn)的類(lèi)體里面,包含3個(gè)以def開(kāi)頭的函數(shù)。第1個(gè)是名為_(kāi)_init__的特殊方法,它是“初始化程序”。在創(chuàng)建對(duì)象時(shí),用來(lái)為代表屬性的諸變量賦初值。例如,類(lèi)Dog里有3個(gè)形參,即self、name、age,除了特殊的self后面會(huì)專門(mén)講述它的作用外,name和age兩個(gè)屬性的初值都會(huì)由創(chuàng)建對(duì)象(即實(shí)例化)語(yǔ)句提供的實(shí)參傳遞過(guò)來(lái)。第2個(gè)是名為sit(坐)的函數(shù),它是描述狗會(huì)“坐”的這種行為的方法。該方法只有一個(gè)特殊參數(shù)self,功能是把狗名的第1個(gè)字母改為大寫(xiě)(由調(diào)用函數(shù)title()來(lái)實(shí)現(xiàn)),并輸出“isnowsitting”信息。如果在此能夠插入一些動(dòng)畫(huà),那么就應(yīng)該出現(xiàn)一條狗蹲坐在那里、舌頭吐在嘴外面呼呼喘氣的情景。第3個(gè)是名為r_over(奔跑)的函數(shù),它是描述狗會(huì)“跑”的這種行為的方法。該方法只有一個(gè)特殊參數(shù)self,功能是把狗名的第1個(gè)字母改為大寫(xiě)(由調(diào)用函數(shù)title()來(lái)實(shí)現(xiàn)),并輸出“rolledover!”信息。如果這里能夠插入動(dòng)畫(huà),那么就應(yīng)該出現(xiàn)一條狗向前奔跑的情景。6.1.2Python中類(lèi)的定義classEmployee(): #定義類(lèi)Employeee_count=0
def__init__(self,name,salary): #初始化程序
=nameself.salary=salaryEmployee.e_count+=1
defdis_employee(self): #輸出雇員信息
print('Name:',,',Salary:',self.salary)例6-2定義一個(gè)“雇員”類(lèi):該類(lèi)的名字是Employee,它的首字母為大寫(xiě),符合Python的約定要求。在縮進(jìn)的類(lèi)體里,先是為一個(gè)變量e_count賦初值0,由于它在類(lèi)體的最前面,所以這個(gè)變量在整個(gè)類(lèi)的定義里都有效,也就是類(lèi)里定義的函數(shù)都可以使用它。6.1.2Python中類(lèi)的定義該類(lèi)里,第1個(gè)是名為_(kāi)_init__的初始化程序,我們后面會(huì)對(duì)它進(jìn)行專門(mén)的講述。除去特殊參數(shù)self外,它的兩個(gè)屬性name、salary的初始值,仍然是在創(chuàng)建對(duì)象(即實(shí)例化)時(shí),靠創(chuàng)建語(yǔ)句通過(guò)實(shí)參傳遞過(guò)來(lái)。在這個(gè)方法里,還對(duì)變量e_count進(jìn)行計(jì)數(shù)操作。該類(lèi)體里的第2個(gè)函數(shù)是dis_employee(),只有一個(gè)特殊參數(shù)self,功能是輸出雇員的名單。importmath #導(dǎo)入標(biāo)準(zhǔn)函數(shù)庫(kù)mathclassCircle(): #定義類(lèi)Circle def__init__(self,radius=14): self.radius=radius defd_diameter(self): #返回直徑的方法
return2*self.radius defc_perimeter(self): #返回圓周長(zhǎng)的方法
return2*self.radius*math.pi defr_area(self): #返回圓面積的方法
returnself.radius*self.radius*math.pi例6-3定義一個(gè)關(guān)于“圓”類(lèi):6.1.2Python中類(lèi)的定義該類(lèi)的名字是Circle,它的首字母為大寫(xiě),符合Python的約定要求。注意,在整個(gè)類(lèi)定義的外面,有一條導(dǎo)入語(yǔ)句“importmath”,表明該類(lèi)里要用到有關(guān)數(shù)學(xué)計(jì)算的標(biāo)準(zhǔn)函數(shù)庫(kù)??s進(jìn)的類(lèi)體里有4個(gè)函數(shù):第1個(gè)仍然是名為_(kāi)_init__的初始化程序,它除了特殊參數(shù)self外,還有一個(gè)名為radius(半徑)的默認(rèn)參數(shù),取默認(rèn)值為14。第2個(gè)方法名為d_diameter,只有一個(gè)特殊參數(shù)self,功能是返回圓的直徑;第3個(gè)方法名為c_perimeter,只有一個(gè)特殊參數(shù)self,功能是返回圓周長(zhǎng);第4個(gè)方法名為r_area,只有一個(gè)特殊參數(shù)self,功能是返回圓面積。6.1.2Python中類(lèi)的定義比較以上給出的3個(gè)類(lèi)的定義,可以得到下面這樣的一些對(duì)類(lèi)的認(rèn)識(shí):當(dāng)使用前面那些單一數(shù)據(jù)類(lèi)型無(wú)法描述出世間的事物時(shí),就應(yīng)該考慮采用“類(lèi)”這種數(shù)據(jù)類(lèi)型;類(lèi)名字的第1個(gè)字母,應(yīng)該遵循大寫(xiě)的規(guī)則;類(lèi)定義中,可以有一個(gè)名為_(kāi)_init__的初始化程序(它實(shí)際上也是一個(gè)方法),在它的里面聚集了抽象出來(lái)的屬性;類(lèi)中的各種方法里,即使是初始化程序,都有一個(gè)特殊的參數(shù)self,它總是被放在方法形參表的第1個(gè)位置處,哪怕方法里沒(méi)有任何別的參數(shù),這個(gè)self都是不可或缺的。綜上所述,Python的類(lèi)的定義,是把解決問(wèn)題時(shí)需要用到的變量(即屬性)和函數(shù)(即方法)組合在了定義中。通常,稱這種組合為“封裝”,前面的那些數(shù)據(jù)類(lèi)型,都不可能實(shí)現(xiàn)這種把變量和方法封裝在一起的效果。01OPTION02OPTION03OPTION04OPTION目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.1.3對(duì)象:類(lèi)的實(shí)例化定義了類(lèi),就可以進(jìn)行類(lèi)的實(shí)例化工作了。也就是說(shuō),可以從“抽象”轉(zhuǎn)為“具體”,創(chuàng)建出一個(gè)個(gè)現(xiàn)實(shí)世界中的對(duì)象來(lái)。創(chuàng)建的對(duì)象可以通過(guò)“對(duì)象名.成員”的方式,訪問(wèn)類(lèi)中所列的<成員變量>和<成員函數(shù)>。例6-2中有關(guān)雇員的實(shí)例化。例如在類(lèi)Employee定義的基礎(chǔ)上,編寫(xiě)程序主體如下:emp1=Employee('Zara',2000) #創(chuàng)建一個(gè)名為emp1的對(duì)象emp2=Employee('Manni',5000) #創(chuàng)建一個(gè)名為emp2的對(duì)象emp1.dis_employee() #emp1調(diào)用方法dis_employee()emp2.dis_employee() #emp2調(diào)用方法dis_employee()print('TotalEmployee%d'%Employee.e_count) #輸出雇員數(shù)6.1.3對(duì)象:類(lèi)的實(shí)例化該程序有3部分內(nèi)容。先是通過(guò)類(lèi)Employee創(chuàng)建兩個(gè)對(duì)象,即emp1和emp2,創(chuàng)建過(guò)程與調(diào)用函數(shù)類(lèi)似,把實(shí)參“'Zara',2000”和“'Manni',5000”分別傳遞給類(lèi)里的形參name和salary。注意,前面一再提及的特殊參數(shù)self沒(méi)有出現(xiàn),沒(méi)有傳遞。其次是創(chuàng)建完對(duì)象后,采用句號(hào)分隔的辦法,用不同的對(duì)象名,兩次調(diào)用類(lèi)中的方法dis_employee(),目的是利用該方法輸出該雇員的信息。注意,類(lèi)中方法里的self參數(shù)仍然沒(méi)有出現(xiàn)。第3個(gè)內(nèi)容是一條print語(yǔ)句,輸出雇員數(shù)e_count。把類(lèi)定義及程序主體合并在一起,然后保存并投入運(yùn)行,結(jié)果如圖6-1所示。這就是一個(gè)簡(jiǎn)單的面向?qū)ο蟮某绦蛟O(shè)計(jì)過(guò)程:先定義一個(gè)類(lèi),把有關(guān)的屬性和方法封裝在一起;然后創(chuàng)建對(duì)象,完成實(shí)例化;最后是程序的執(zhí)行,獲得所需要的結(jié)果。圖6-16.1.3對(duì)象:類(lèi)的實(shí)例化classEmployee():e_count=0def__init__(self,name,salary):=nameself.salary=salaryEmployee.e_count+=1defdis_employee(self):print('Name:',,',Salary:',self.salary)emp1=Employee('Zara',2000) #創(chuàng)建一個(gè)名為emp1的對(duì)象emp2=Employee('Manni',5000) #創(chuàng)建一個(gè)名為emp2的對(duì)象emp1.dis_employee() #emp1調(diào)用方法dis_employee()emp2.dis_employee() #emp2調(diào)用方法dis_employee()print('TotalEmployee%d'%Employee.e_count) #輸出雇員數(shù)程序編寫(xiě)如下:6.1.3對(duì)象:類(lèi)的實(shí)例化firstA=Circle(17) #創(chuàng)建一個(gè)名為firstA的對(duì)象firstB=Circle() #創(chuàng)建一個(gè)名為firstB的對(duì)象print('InformationonfirstA:')print('Radiusofthegarden',firstA.radius)print('Diameterofthegarden:',firstA.d_diameter())print('Gardenarea:',firstA.r_area())print('Gardenperimeter:',firstA.c_perimeter())print('\nInformationonfirstB:')print('Radiusofthegarden',firstB.radius)print('Diameterofthegarden:',firstB.d_diameter())print('Gardenarea:',firstB.r_area())print('Gardenperimeter:',firstB.c_perimeter())再來(lái)看例6-3里定義的“圓”類(lèi),編寫(xiě)程序主體如下:6.1.3對(duì)象:類(lèi)的實(shí)例化程序開(kāi)始處,通過(guò)類(lèi)Circle創(chuàng)建了兩個(gè)對(duì)象,一個(gè)名為firstA,一個(gè)名為firsrB。在類(lèi)Circle的初始化程序里,除了特殊參數(shù)self外,有一個(gè)默認(rèn)參數(shù)radius,創(chuàng)建firstA對(duì)象時(shí),沒(méi)有使用這個(gè)默認(rèn)參數(shù),而是把自己的參數(shù)值17傳遞了過(guò)去;創(chuàng)建firstB對(duì)象時(shí),使用了默認(rèn)參數(shù),所以無(wú)須傳遞任何參數(shù)給類(lèi)的初始化程序。這些用法完全與函數(shù)相同。緊接著是分兩組輸出語(yǔ)句輸出兩個(gè)實(shí)例化的圓的半徑、圓的直徑、圓的面積、圓的周長(zhǎng)。把類(lèi)定義及程序主體合并在一起,然后保存并執(zhí)行,結(jié)果如圖6-2所示。圖6-26.1.3對(duì)象:類(lèi)的實(shí)例化importmathclassCircle(): def__init__(self,radius=14): self.radius=radius defd_diameter(self): return2*self.radius defc_perimeter(self): return2*self.radius*math.pi defr_area(self): returnself.radius*self.radius*math.pi程序編寫(xiě)如下:firstA=Circle(17)firstB=Circle()print('InformationonfirstA:')print('Radiusofthegarden',firstA.radius)print('Diameterofthegarden:',firstA.d_diameter())print('Gardenarea:',firstA.r_area())print('Gardenperimeter:',firstA.c_perimeter())print('\nInformationonfirstB:')print('Radiusofthegarden',firstB.radius)print('Diameterofthegarden:',firstB.d_diameter())print('Gardenarea:',firstB.r_area())print('Gardenperimeter:',firstB.c_perimeter())目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.2.1關(guān)于初始化程序:__init__下面羅列幾個(gè)編寫(xiě)初始化程序時(shí)需要了解的問(wèn)題。#下面是定義的函數(shù),它有了返回值defodd_even(x): if(x%2==0): result=True else: result=False returnresult #return必須保證在函數(shù)體的縮進(jìn)范圍內(nèi)#下面是調(diào)用函數(shù)的程序print('Pleaseenteraninteger!')num=input('Enteraninteger:')y=int(num)#調(diào)用函數(shù)odd_even(),變量z接收函數(shù)的返回值z(mì)=odd_even(y) ifz==True: print('It\'sanevennumber!')else: print('It\'sanoddnumber!')print('End')6.2.1關(guān)于初始化程序:__init__下面羅列幾個(gè)編寫(xiě)初始化程序時(shí)需要了解的問(wèn)題。1.初始化程序的正確寫(xiě)法:兩條下劃線初始化程序的名字,是以兩條下劃線開(kāi)始,以兩條下劃線結(jié)束的。如果哪一邊只有一條下劃線,那么就會(huì)輸出圖6-3所示的出錯(cuò)信息,表明創(chuàng)建對(duì)象時(shí),實(shí)參無(wú)法傳遞給類(lèi),導(dǎo)致對(duì)象得不到參數(shù)。這種錯(cuò)誤提示得非常隱晦,讓人難以發(fā)現(xiàn)到底是在哪里出了問(wèn)題,其實(shí)只是因?yàn)閬G失了一條小小的下劃線“—”。2.初始化程序,不一定非要排在類(lèi)定義的最前面初始化程序的名字是固定的,只能寫(xiě)成“__init__”。因此,只要保證它出現(xiàn)在類(lèi)定義語(yǔ)句塊的里面就行,至于是塊中的第1個(gè)方法(如例6.1~6.3那樣),還是第幾個(gè)方法,完全無(wú)關(guān)緊要;甚至如果不需要傳遞什么參數(shù),在類(lèi)的定義中不編寫(xiě)初始化程序也沒(méi)有什么關(guān)系。Python在創(chuàng)建一個(gè)新的對(duì)象(即實(shí)例化)時(shí),總是用這個(gè)名字去匹配類(lèi)中所包含的方法名,找到這個(gè)名字,就執(zhí)行并僅執(zhí)行它一次,以完成初始化的工作;如果沒(méi)有找到它,那就不做初始化工作。6.2.1關(guān)于初始化程序:__init__3.初始化程序中name與的不同含義例如在例6-2的類(lèi)定義中,初始化程序如下:def__init__(self,name,salary):=nameself.salary=salaryEmployee.e_count+=1在它的里面除self外,還有兩個(gè)位置參數(shù):name、salary。一進(jìn)入初始化程序,就執(zhí)行:=nameself.salary=salary把接收到的實(shí)參(在name和salary里),賦予變量和self.salary。因此,這兩條語(yǔ)句右邊的name和salary,是初始化程序接收到的傳遞過(guò)來(lái)的實(shí)參,而左邊的與self.salary是兩個(gè)變量,由它們接收并存放這個(gè)新建對(duì)象的具體屬性值。6.2.1關(guān)于初始化程序:__init__既然左邊的與self.salary是兩個(gè)變量名稱,因此除了前面的self不能變以外,句號(hào)分隔的name與salary完全可以另取名字,例如改名為self.ad和self.bc,這也是完全可以接受的。人們之所以喜歡將它們?nèi)∶麨榕cself.salary,主要是因?yàn)閚ame、salary是類(lèi)的屬性名,有它們就知道這個(gè)變量里面存放的是什么屬性值。例如,把前面給出的類(lèi)Dog里面的:=nameself.age=age改為:self.ad=nameself.bc=age6.2.1關(guān)于初始化程序:__init__classDog(): def__init__(self,name,age): self.ad=name #變量名變了
self.bc=age #變量名變了
defsit(self): print(self.ad.title()+'isnowsitting.') #這里要做相應(yīng)改動(dòng)
defr_over(self): print(self.ad.title()+'rolledover!') #這里要做相應(yīng)改動(dòng)mdog=Dog('willams',6)print('Mydog\'snameis'+str(mdog.ad.title())+'.') #這里要做相應(yīng)改動(dòng)print('Mydogis'+str(mdog.bc)+'yearold!') #這里要做相應(yīng)改動(dòng)整個(gè)類(lèi)和程序如下所示:運(yùn)行該程序,完全可以得到正確的結(jié)果。不過(guò)要注意的是,如果把類(lèi)中接收實(shí)參值的變量名改了,那么程序中相應(yīng)的地方也都要改動(dòng),否則就會(huì)出錯(cuò)。目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.2.2關(guān)于參數(shù):self例6-4下面是一個(gè)用類(lèi)編寫(xiě)的極為簡(jiǎn)單的圖書(shū)查詢的例子(為方便講述,各部分程序分散列在下面):#定義一個(gè)字典catalogcatalog={'aa':3,'bb':0,'cc':5,'dd':2,'ee':4,'ff':1,'gg':8,'hh':3}#定義類(lèi)BookclassBook(): globalcatalog def__init__(self,name): =name #下面是類(lèi)中的方法loop(),供創(chuàng)建的對(duì)象調(diào)用
defloop(self,name): forkey,valueincatalog.items(): ifkey==name: ifvalue!=0: print('Thereisthebook!') elifvalue==0: print('I\'msorrythatthebookhasbeenborrowed!') else: print('It\'sapitythatthereisnobook!') break6.2.2關(guān)于參數(shù):self#下面是類(lèi)中的方法seek(),供創(chuàng)建的對(duì)象調(diào)用defseek(self,pword,name,value): ifpword!='12345': returnprint('Youdon\'thavetherighttoaddanewbook!') else: catalog[name]=value print(catalog)整個(gè)程序開(kāi)始,先定義一個(gè)字典catalog,書(shū)名aa、bb、cc等是字典的鍵;現(xiàn)存書(shū)的數(shù)量是字典的值。由于字典catalog是在整個(gè)程序外定義的,進(jìn)入類(lèi)后才使用它,這樣可能會(huì)引起不必要的誤解,所以在類(lèi)的里面用語(yǔ)句globalcatalog表明類(lèi)里出現(xiàn)的catalog就是外面定義的全局變量catalog。整個(gè)類(lèi)Book里有3個(gè)函數(shù)。6.2.2關(guān)于參數(shù):self第1個(gè)是初始化程序__init__,它有兩個(gè)參數(shù),一個(gè)是self,一個(gè)是name。實(shí)例化時(shí),name將接收傳遞過(guò)來(lái)的書(shū)名,并將其賦予變量。第2個(gè)方法名為loop,它有兩個(gè)參數(shù),一個(gè)是self,一個(gè)是是希望查找的書(shū)名,通過(guò)對(duì)字典catalog的遍歷,給出查找的結(jié)果。在查找過(guò)程中,考慮這樣幾個(gè)問(wèn)題:找到,且當(dāng)前有這本書(shū)(數(shù)量不為0);找到,但當(dāng)前沒(méi)有這本書(shū)可外借(數(shù)量為0);沒(méi)有找到這本書(shū),查找失敗。不同的情況會(huì)輸出不同的信息:找到且當(dāng)前有此書(shū),輸出信息“Thereisthebook!”;找到但當(dāng)前沒(méi)有這本書(shū),輸出信息“I'msorrythatthebookhasbeenborrowed!”;沒(méi)有找到所需要的書(shū),則輸出信息“It'sapitythatthereisnobook!”。第3個(gè)方法名為seek,它有4個(gè)參數(shù),self、pword、name、value。后面3個(gè)參數(shù),一個(gè)是口令(pword)、一個(gè)是要添加的書(shū)名(name)、一個(gè)是數(shù)量(value)。只有在調(diào)用方法loop()查找沒(méi)有結(jié)果時(shí),才有可能往字典里添加新書(shū);只有在輸入的口令正確時(shí),才能往字典里添加新書(shū)。也就是說(shuō),不是隨便什么人都可以往字典里添加新書(shū)的。6.2.2關(guān)于參數(shù):self程序主體分為兩段:一個(gè)是創(chuàng)建類(lèi)Book的對(duì)象studentA,在輸入書(shū)名后,調(diào)用類(lèi)的方法loop(),以便查找是否有所需的書(shū)目;另一個(gè)是創(chuàng)建類(lèi)Book的對(duì)象studentB,在輸入書(shū)名后,調(diào)用類(lèi)的方法loop(),只有在調(diào)用方法loop()無(wú)結(jié)果的情況下,才去輸入口令、數(shù)量,才去調(diào)用方法seek(),才有可能把新書(shū)添加到字典中去。程序編寫(xiě)如下:#下面是程序中創(chuàng)建的對(duì)象studentAbk=input('Enterthetitleoftherequiredbook:')studentA=Book(bk)studentA.loop(bk)#下面是程序中創(chuàng)建的對(duì)象studentBbnm=input('Enterbookname:')studentB=Book(bnm)studentB.loop(bnm)psw=input('Enterpassword:')num=input('Enternubmer:')studentB.seek(psw,bnm,num)目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.2.3關(guān)于類(lèi)的屬性1.給類(lèi)的屬性指定默認(rèn)值借助上面的例6-4,在類(lèi)Book的定義里,給出一個(gè)取默認(rèn)值的屬性“self.word='12345'”,并利用它作為口令的初始值。圖6-4所示是兩次運(yùn)行的情形,一次是口令輸入正確,將希望添加的書(shū)目(書(shū)名:xx,數(shù)量:3)添加到字典里;一次是口令輸入錯(cuò)誤,無(wú)法將書(shū)目添加到字典里去。這時(shí)的程序(缺少創(chuàng)建對(duì)象部分)如下:catalog={'aa':3,'bb':0,'cc':5,'dd':2,'ee':4,'ff':1,'gg':8,'hh':3}classBook(): globalcatalog def__init__(self,name): =name self.word='12345' #設(shè)置屬性word默認(rèn)的初始值,它不出現(xiàn)在參數(shù)表里6.2.3關(guān)于類(lèi)的屬性defloop(self,name): forkey,valueincatalog.items(): ifkey==name: ifvalue!=0: print('Thereisthebook') elifvalue==0: print('I\'msorrythatthebookhasbeenborrowed!') else: print('It\'apitythatthereisnobook!') breakdefseek(self,pword,name,value): ifpword!=self.word: #用到屬性word默認(rèn)的初始值 returnprint('Youdon\'thavetherighttoaddanewbook!') else: catalog[name]=value print(catalog)6.2.3關(guān)于類(lèi)的屬性bnm=input('Enterbookname:')studentB=Book(bnm)studentB.loop(bnm)psw=input('Enterpassword:')num=input('Enternubmer:')studentB.seek(psw,bnm,num)圖6-42.對(duì)類(lèi)的默認(rèn)屬性值的修改每種類(lèi)都有自己的屬性和方法,屬性是從類(lèi)的實(shí)例化中抽象出來(lái)的特征,由變量來(lái)描述;方法是從類(lèi)的實(shí)例化中抽象出來(lái)的行為,由函數(shù)來(lái)描述。因此,修改類(lèi)的屬性值,就是修改描述它的變量的值,這是非常容易做到的事情。6.2.3關(guān)于類(lèi)的屬性修改默認(rèn)屬性值最直接的辦法,是在創(chuàng)建的實(shí)例里進(jìn)行。例如上面原先設(shè)置的默認(rèn)屬性值是:self.word='12345'只要在實(shí)例化studentB的程序里,增加一條語(yǔ)句:studentB.word='67890'于是,現(xiàn)在創(chuàng)建對(duì)象studentB時(shí)的程序就改寫(xiě)為:bnm=input('Enterbookname:')studentB=Book(bnm)studentB.loop(bnm)studentB.word='67890' #對(duì)默認(rèn)屬性值的修改psw=input('Enterpassword:')num=input('Enternubmer:')studentB.seek(psw,bnm,num)這時(shí)再運(yùn)行程序,只有輸入的口令是“67890”,才會(huì)允許將輸入的書(shū)目和數(shù)量添加到字典catalog里;否則是通不過(guò)口令的檢查的。6.2.3關(guān)于類(lèi)的屬性3.屬性的增、刪、改定義一個(gè)類(lèi)并創(chuàng)建了它的對(duì)象后,可以對(duì)定義的類(lèi)進(jìn)行添加新屬性、修改原有屬性、刪除已有屬性的操作。下面的程序中,定義了一個(gè)名為Car的類(lèi),它有一個(gè)形參col,有兩個(gè)默認(rèn)參數(shù):price=100000和name=“QQ”。#定義的類(lèi)Car:classCar: def__init__(self,col): self.color=col self.price=100000 ='QQ'#程序主體:car1=Car('Red')print(,car1.color,car1.price)car1.price=110000car1.color='Yellow'car1.time='2016/08'print(,car1.color,car1.price,car1.time)delcar1.colorprint(,car1.color,car1.price,car1.time)print('End')6.2.3關(guān)于類(lèi)的屬性程序主體里,創(chuàng)建了一個(gè)名為car1的對(duì)象,隨之通過(guò)語(yǔ)句:print(,car1.color,car1.price)輸出信息“QQRed100000”。接著有語(yǔ)句:car1.price=110000car1.color='Yellow'car1.time='2016/08'前兩條是修改已有屬性price和color,后一條語(yǔ)句是增加新屬性time(出廠時(shí)間)。這樣的操作,使得程序主體中的第2條輸出語(yǔ)句輸出了這輛QQ的新信息。最后,通過(guò)語(yǔ)句:delcar1.color刪除對(duì)象car1的屬性color。第3條輸出語(yǔ)句的執(zhí)行,就會(huì)產(chǎn)生出錯(cuò)信息:AttributeError:'Car'objecthasnoattribute'color'6.2.3關(guān)于類(lèi)的屬性表示試圖刪除對(duì)象沒(méi)有的屬性,操作失敗。圖6-5記錄了程序的整個(gè)執(zhí)行過(guò)程。圖6-54.屬性的保護(hù)如上所述,在程序主體中可以對(duì)對(duì)象的屬性進(jìn)行增、刪、改等操作。這種做法看似很方便,用起來(lái)也得心應(yīng)手,但卻違反了類(lèi)的封裝原則:數(shù)據(jù)使用的安全性。對(duì)象能夠在類(lèi)定義的外部隨便訪問(wèn)其數(shù)據(jù)屬性,就有可能修改它們,影響到類(lèi)中提供的各種方法的正確運(yùn)行,因?yàn)樵陬?lèi)定義里給出的方法里面可能會(huì)用到屬性變量。6.2.3關(guān)于類(lèi)的屬性類(lèi)定義中的屬性變量沒(méi)有了私密性,就可能會(huì)帶來(lái)各種想象不到的麻煩??紤]到這些問(wèn)題,Python對(duì)類(lèi)的屬性提供了一種自我保護(hù)的簡(jiǎn)單辦法。具體做法如下。classCar: def__init__(self,col): self.__color=col self.price=100000 ='QQ' defpri(self): print(self.__color)01OPTION02OPTION在需要具有私密性的屬性變量名前,加上雙下劃線。在類(lèi)定義里增加供程序設(shè)計(jì)人員訪問(wèn)屬性變量的接口。仍以上面所定義的類(lèi)Car來(lái)加以說(shuō)明。car1=Car('Red')print(,car1.price)car1.pri()print('End')6.2.3關(guān)于類(lèi)的屬性假定要保護(hù)屬性col的使用,不允許在程序主體內(nèi)隨意地訪問(wèn)它,那么可以在類(lèi)定義中,在接收col的形參名前增加雙下劃線,即:self.__color另一方面,在類(lèi)定義中寫(xiě)一個(gè)輸出汽車(chē)顏色的方法:defpri(self): print(self.__color)以便在程序主體內(nèi)能夠輸出汽車(chē)的顏色。classCar: def__init__(self,col): self.__color=col self.price=100000 ='QQ'先看一下在形參名前加上雙下劃線后的作用。這時(shí)整個(gè)程序是這樣的:car1=Car('Red')print(,car1.price,car1.color)print('End')6.2.3關(guān)于類(lèi)的屬性運(yùn)行該程序,結(jié)果如圖6-6所示,給出出錯(cuò)信息:AttributeError:'Car'objecthasnoattribute'color'之所以會(huì)這樣,是因?yàn)轭?lèi)定義里,在屬性color變量名前加上了雙下劃線,Python對(duì)該變量進(jìn)行了保護(hù),不允許在類(lèi)外通過(guò)“car1.color”直接訪問(wèn)該屬性。為了能夠在類(lèi)定義外訪問(wèn)屬性color,可以在類(lèi)定義里給出訪問(wèn)該變量的函數(shù),例如pri(),然后在程序主體里,把語(yǔ)句“print(,car1.price,car1.color)”改寫(xiě)成語(yǔ)句“print(,car1.price)”,增加語(yǔ)句“car1.pri()”。這樣再運(yùn)行,程序就正確了,如圖6-7所示。圖6-6圖6-76.2.3關(guān)于類(lèi)的屬性classCar: def__init__(self,col): self.__color=col self.price=100000 ='QQ' defpri(self):
#增加的新函數(shù)
print(self.__color)car1=Car('Red')print(,car1.price) #去除直接訪問(wèn)屬性color的內(nèi)容car1.pri()
#增加調(diào)用類(lèi)函數(shù)pri()的語(yǔ)句print('End')程序編寫(xiě)如下:目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.3.1Python里類(lèi)的繼承只要遵守Python里“繼承”的規(guī)則,在程序設(shè)計(jì)中完成繼承是不困難的。例如,簡(jiǎn)單定義了一個(gè)名為People的類(lèi),代碼如下:“繼承”,即承上啟下。一個(gè)類(lèi),就是把它所要描述事物的特征(即屬性)和行為(即方法)包裝(也就是封裝)在了一起。在繼承關(guān)系中,已有的、設(shè)計(jì)好的類(lèi)被稱為“父類(lèi)”或“基類(lèi)”,新設(shè)計(jì)的類(lèi)被稱為“子類(lèi)”或“派生類(lèi)”。classPeople(): def__init__(self,name,nationality): =name self.nationality=nationality deftalk(self): print('Communicateinlanguage') defwalk(self): print('Walkuprightwithyourlegs!')6.3.1Python里類(lèi)的繼承由它派生出來(lái)的類(lèi),都應(yīng)該有這樣的屬性和方法,也就是說(shuō)都會(huì)繼承這些屬性和方法。下面定義一個(gè)名為Ch_people(中國(guó)人)的類(lèi):該類(lèi)名為People,它有3個(gè)屬性:self、name、nationality(國(guó)籍)。類(lèi)中定義了兩個(gè)方法,一是talk,調(diào)用它時(shí)輸出信息“Communicateinlanguage”(用語(yǔ)言交流);二是walk,調(diào)用它時(shí)輸出信息“Walkuprightwithyourlegs”(兩腿直立行走)。classCh_people(People): #定義一個(gè)子類(lèi),名為Ch_people pass #表示該類(lèi)不做什么事情在該類(lèi)名字后面的括號(hào)里,填寫(xiě)了一個(gè)參數(shù)“People”,表明它是從類(lèi)People派生出來(lái)的,要繼承它的“衣缽”,也就是繼承它的所有屬性和方法。該類(lèi)的類(lèi)體里只有一條語(yǔ)句“pass”,表示雖然定義了這個(gè)新類(lèi),但它什么事情也不做,它沒(méi)有自己新的屬性,也沒(méi)有自己新的方法,純粹就是一個(gè)“空”的類(lèi)。6.3.1Python里類(lèi)的繼承定義了類(lèi)People和類(lèi)Ch_people后,編寫(xiě)如下程序:#創(chuàng)建類(lèi)People的一個(gè)對(duì)象peopApeopA=People('Zongdahua','china') print(peopA.name,peopA.nationality)peopA.talk()peopA.walk()#創(chuàng)建類(lèi)Ch_people的另一個(gè)對(duì)象peopBpeopB=Ch_people('Zongdahua','china') print(peopB.name,peopB.nationality)peopB.talk()peopB.walk()執(zhí)行整個(gè)程序,結(jié)果如圖6-8所示。圖6-86.3.1Python里類(lèi)的繼承上半部分是類(lèi)People的對(duì)象peopA調(diào)用方法的結(jié)果;下半部分是類(lèi)Ch_people的對(duì)象peopB調(diào)用方法的結(jié)果。由于類(lèi)Ch_people是由類(lèi)People派生出來(lái)的,它繼承了類(lèi)People的一切,自己又不多做任何事情,所以這兩個(gè)對(duì)象的運(yùn)行結(jié)果是完全一樣的。為了便于描述,常會(huì)使用如下的名稱?;?lèi):也稱“父類(lèi)”,表示這種類(lèi)是可以被別的類(lèi)繼承的。派生類(lèi):也稱“子類(lèi)”,表示這種類(lèi)是一個(gè)繼承別的類(lèi)的類(lèi)。例如,上面定義的類(lèi)People,相對(duì)于類(lèi)Ch_people來(lái)說(shuō),就是一個(gè)基類(lèi),即父類(lèi);而定義的類(lèi)Ch_people,則是一個(gè)從類(lèi)People派生出來(lái)的類(lèi),因此是一個(gè)子類(lèi)??偨Y(jié),在Python里,要從一個(gè)類(lèi)里派生出另一個(gè)類(lèi),也就是一個(gè)類(lèi)要繼承另外一個(gè)類(lèi),只需將父類(lèi)的名字放入該類(lèi)定義的括號(hào)里即可。由于在子類(lèi)的定義里只有一條pass語(yǔ)句,所以它將會(huì)從它的父類(lèi)那里繼承所有的特征和行為。目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法在繼承機(jī)制下,允許子類(lèi)改寫(xiě)父類(lèi)中已經(jīng)出現(xiàn)過(guò)的方法。通常,這種改寫(xiě)被稱為“覆蓋”。deftalk(self): print('Communicateinlanguage')加以改寫(xiě)(也就是“覆蓋”),例如改寫(xiě)為:deftalk(self): print('ExchangeideasinChinese!')classCh_people(People): deftalk(self): print('ExchangeideasinChinese!')仍以類(lèi)Ch_people這個(gè)由類(lèi)People派生出來(lái)的類(lèi)為例。類(lèi)Ch_people當(dāng)然是用語(yǔ)言來(lái)交流思想的,但類(lèi)Ch_people是用特定的、自己民族的語(yǔ)言來(lái)交流思想的。因此,在定義類(lèi)Ch_people時(shí),可以將原先類(lèi)People中的方法:這樣,類(lèi)Ch_people的定義就可以是:6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法即先取消類(lèi)Ch_people定義中的pass語(yǔ)句,然后再改寫(xiě)方法talk()?,F(xiàn)在,整個(gè)程序變?yōu)椋篶lassPeople(): def__init__(self,name,nationality): =name self.nationality=nationality deftalk(self): print('Communicateinlanguage') defwalk(self): print('Walkontwolegs')classCh_people(People): deftalk(self): #改寫(xiě)父類(lèi)中的同名方法talk() print('ExchangeideasinChinese!')peopA=People('Zongdahua','china')print(peopA.name,peopA.nationality)peopA.talk()peopA.walk()peopB=Ch_people('Zongdahua','china')print(peopB.name,peopB.nationality)peopB.talk()peopB.walk()6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法運(yùn)行該程序,結(jié)果就與圖6-8有所不同了,如圖6-9所示。圖6-9這時(shí)在子類(lèi)中,利用改寫(xiě)的初始化程序,就可以使子類(lèi)增添自己特有的屬性。例如,原先類(lèi)People只有name和nationality兩個(gè)屬性,考慮到中國(guó)是一個(gè)多民族國(guó)家,希望在類(lèi)Ch_people里,增加一個(gè)名為nation的屬性。為此,可以在類(lèi)Ch_people里,改寫(xiě)類(lèi)People里的初始化程序,代碼如下:classCh_people(People):def__init__(self,name,nationality,nation):=nameself.nationality=nationalityself.nation=nation6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法當(dāng)創(chuàng)建類(lèi)Ch_people的對(duì)象時(shí),Python就去執(zhí)行該類(lèi)如上的初始化程序,從創(chuàng)建處傳遞所需的實(shí)參給變量、self.nationality、self.nation,完成初始化工作,以保證整個(gè)程序正常運(yùn)行。下面是整個(gè)程序的內(nèi)容:classPeople(): def__init__(self,name,nationality): =name self.nationality=nationality deftalk(self): print('Communicateinlanguage') defwalk(self): print('Walkontwolegs')classCh_people(People):def__init__(self,name,nationality,nation):=nameself.nationality=nationalityself.nation=nationdeftalk(self):print('Exchangeideaswithnationallanguage!')peopA=People('Zongdahua','china')print(peopA.name,peopA.nationality)peopA.talk()peopA.walk()peopB=Ch_people('Zongdahua','china','Chinese')print(peopB.name,peopB.nationality,peopB.nation)peopB.talk()peopB.walk()6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法運(yùn)行該程序,結(jié)果就與圖6-9又不一樣了,如圖6-10所示。圖6-10目錄導(dǎo)航6.1類(lèi)和對(duì)象6.1.1類(lèi)與對(duì)象的概念6.1.3對(duì)象:類(lèi)的實(shí)例化6.2對(duì)類(lèi)的進(jìn)一步認(rèn)識(shí)6.1.2Python中類(lèi)的定義6.2.1關(guān)于初始化程序:__init__6.2.2關(guān)于參數(shù):self6.2.3關(guān)于類(lèi)的屬性6.3類(lèi)的繼承6.4Python中類(lèi)的導(dǎo)入6.3.1Python里類(lèi)的繼承6.3.2在子類(lèi)中改寫(xiě)父類(lèi)的方法6.4.1類(lèi)的導(dǎo)入6.4.2導(dǎo)入多個(gè)類(lèi)6.3.3內(nèi)置函數(shù)super()6.3.4多重繼承6.3.3內(nèi)置函數(shù)super()實(shí)際應(yīng)用中,肯定會(huì)有這樣的情形發(fā)生:子類(lèi)改寫(xiě)了父類(lèi)的某個(gè)方法,后面卻還要用到已被改寫(xiě)的原先父類(lèi)的那個(gè)方法。Python的內(nèi)置函數(shù)super()就可以解決這個(gè)問(wèn)題,它建立起了子類(lèi)與父類(lèi)之間的聯(lián)系,準(zhǔn)確無(wú)誤地在子類(lèi)里找到父類(lèi),并實(shí)現(xiàn)對(duì)所需方法的調(diào)用。也就是說(shuō),如果需要在子類(lèi)中調(diào)用父類(lèi)的方法,那么可以使用內(nèi)置函數(shù)super(),或者通過(guò)“父類(lèi)名.方法名()”的方式,來(lái)達(dá)到這一目的。classParent(): defspeak(self): print('Thevoiceofthefather\'svoice!')classChild(Parent): passdad=Parent()son=Child()dad.speak()son.speak()例6-5一個(gè)全部繼承的例子:6.3.3內(nèi)置函數(shù)super()例中先定義了一個(gè)名為Parent的類(lèi),它有一個(gè)方法speak(),功能是輸出信息“Thevoiceofthefather'svoice!”(父親的說(shuō)話聲音)。接著定義一個(gè)名為Child的類(lèi),它無(wú)條件地繼承了類(lèi)Parent,因?yàn)樗x的括號(hào)里,有一個(gè)參數(shù)“Parent”,且類(lèi)體里只有一條pass語(yǔ)句。程序里共有4條語(yǔ)句:第1條是dad=Parent(),它創(chuàng)建了一個(gè)名為dad的Parent對(duì)象;第2條語(yǔ)句是son=Child(),它創(chuàng)建了一個(gè)名為son的Child對(duì)象;第3條語(yǔ)句是對(duì)象dad調(diào)用方法speak();第4條語(yǔ)句是對(duì)象son調(diào)用方法speak()。由于子類(lèi)Child全盤(pán)地繼承了父類(lèi),所以這兩個(gè)對(duì)象調(diào)用方法speak()的結(jié)果,都是輸出信息“Thevoiceofthefather'svoice!”。6.3.3內(nèi)置函數(shù)super()如圖6-11最上面所示。圖6-116.3.3內(nèi)置函數(shù)super()classParent(): defspeak(self): print('Thevoiceofthefather\'svoice!')classChild(Parent): defspeak(self): print('Thevoiceoftheson\'svoice!')dad=Parent()son=Child()dad.speak()son.speak()把例6-5稍加修改,代碼如下:例6-6一個(gè)覆蓋父類(lèi)方法的例子。6.3.3內(nèi)置函數(shù)super()其他地方都沒(méi)有動(dòng),只是子類(lèi)雖然仍繼承父類(lèi),但并沒(méi)有全盤(pán)繼承,而是修改了父類(lèi)的方法speak(),即如果子類(lèi)的對(duì)象再調(diào)用方法speak(),不是輸出信息“Thevoiceofthefather'svoice!”,而是輸出信息“Thevoiceoftheson'svoice!”。程序的運(yùn)行結(jié)果如圖6-11中間所示:父類(lèi)的方法speak()被子類(lèi)改寫(xiě)的方法speak()覆蓋了。圖6-116.3.3內(nèi)置函數(shù)super()classParent(): defspeak(self): print('Thevoiceofthefather\'svoice!')classChild(Parent): defspeak(self): print('Thevoiceoftheson\'svoice!') super(Child,self).speak()dad=Parent()son=Child()dad.speak()son.speak()把例6-6稍加修改,代碼如下:例6-7利用內(nèi)置函數(shù)super()的例子6.3.3內(nèi)置函數(shù)super()其他地方都沒(méi)有動(dòng),只是子類(lèi)雖然仍繼承了父類(lèi),并改寫(xiě)了父類(lèi)的方法speak(),但它的改寫(xiě)又與例6-6不同,即增加了一條內(nèi)置函數(shù)super()調(diào)用方法speak()的語(yǔ)句“super(Child,self).speak()”。通常,內(nèi)置函數(shù)super()有兩個(gè)參數(shù),第2個(gè)是self,表示自己;第1個(gè)則是一個(gè)類(lèi)名,表示內(nèi)置函數(shù)要調(diào)用的方法是這個(gè)類(lèi)的父類(lèi)的那個(gè)方法。例如在上述程序中,內(nèi)置函數(shù)的第1個(gè)參數(shù)是Child,因此表明它要調(diào)用的那個(gè)方法speak(),是父類(lèi)Child里的那個(gè)方法speak(),而不是自己覆蓋的那個(gè)方法speak()。按照這樣對(duì)內(nèi)置函數(shù)super()的理解,我們來(lái)看程序中最后兩條語(yǔ)句的執(zhí)行結(jié)果。dad是類(lèi)Parent的實(shí)例化,son是類(lèi)Child的實(shí)例化。于是,執(zhí)行語(yǔ)句dad.speak(),就是輸出信息:Thevoiceofthefather'svoice!6.3.3內(nèi)置函數(shù)super()執(zhí)行語(yǔ)句son.speak(),就是要執(zhí)行:print('Thevoiceoftheson\'svoice!')super(Child,self).speak()第1句好理解,即輸出信息:Thevoiceoftheson'svoice!第2句的意思是要去調(diào)用類(lèi)Child的父類(lèi)的方法speak()。于是就去執(zhí)行類(lèi)Parent的方法speak(),即輸出信息:Thevoiceofthefather'svoice!于是,該例的執(zhí)行結(jié)果如圖6-11最后面所示,即輸出結(jié)果:Thevoiceofthefather'svoice!Thevoiceoftheson'svoice!Thevoiceofthefather'svoice!6.3.3內(nèi)置函數(shù)super()在Python中繼承有以下幾個(gè)特點(diǎn)。01OPTION02OPTION03OPTION在繼承中,父類(lèi)的初始化程序__init__不會(huì)被自動(dòng)調(diào)用,Python會(huì)先在其派生類(lèi)的初始化程序中去尋找并調(diào)用,只有當(dāng)子類(lèi)中沒(méi)有初始化程序時(shí),才以父類(lèi)的初始化程序作為自己的初始化程序。在子類(lèi)對(duì)象里調(diào)用父類(lèi)的方法時(shí),需要以父類(lèi)的類(lèi)名作為前綴,并用“.”分隔,還需要帶上self參數(shù)變量。但在一般的類(lèi)中調(diào)用方法時(shí),并不需要帶上self參數(shù)。Python總是首先查找對(duì)應(yīng)類(lèi)的方法,如果它不能在派生類(lèi)中找到對(duì)應(yīng)的方法,它才開(kāi)始到父類(lèi)中去逐個(gè)查找。即先在子類(lèi)中查找調(diào)用的方法,找不到才去父類(lèi)中查找。6.3.3內(nèi)置函數(shù)super()classParent(): def__init__(self): #父類(lèi)的初始化程序
self.parent='I\'mtheparent.' print('Parent') deffun(self,message): #父類(lèi)的方法fun() print('%sfromparent'%message)classChild(Parent): #子類(lèi)的初始化程序
def__init__(self): super(Child,self).__init__() print('Child') deffun(self,message): #子類(lèi)的方法fun() super(Child,self).fun(message) print('Childfunfuction') print(self.parent)#程序主體f_Child=Child()f_Child.fun('HelloPython!')下面是編寫(xiě)的整個(gè)程序,其運(yùn)行結(jié)果如圖6-12所示:例6-8閱讀并對(duì)照運(yùn)行結(jié)果,更進(jìn)一步地理解內(nèi)置函數(shù)super()。6.3.3內(nèi)置函數(shù)super()整個(gè)程序分為3個(gè)部分:第1部分定義了名為Parent的類(lèi),它有一個(gè)初始化程序、一個(gè)名為fun的方法。第2部分定義了一個(gè)名為Child的類(lèi),類(lèi)Parent是它的父類(lèi),它有自己的初始化程序,也有一個(gè)名為fun的方法,也就是說(shuō),這個(gè)方法覆蓋了它父類(lèi)中同名的方法。第3部分是程序主體,它僅由兩條語(yǔ)句組成:第1條語(yǔ)句是對(duì)類(lèi)Child的實(shí)例化,對(duì)象變量是f_Child;第2條語(yǔ)句是該對(duì)象以“HelloPython!”為參數(shù),調(diào)用方法fun()。執(zhí)行這樣的兩條簡(jiǎn)單語(yǔ)句,得到的輸出信息居然會(huì)如圖6-12所示。為什么會(huì)是這樣呢?f_Child=Child()f_Child.fun('HelloPython!')6.3.3內(nèi)置函數(shù)super()分析執(zhí)行語(yǔ)句“f_Child=Child()”的情形。這是創(chuàng)建類(lèi)Child的一個(gè)對(duì)象,對(duì)象的名字是f_Child。類(lèi)Child繼承了類(lèi)Parent,且有自己的初始化程序(也就是它改寫(xiě)了父類(lèi)的初始化程序),因此創(chuàng)建類(lèi)Child的對(duì)象時(shí),不會(huì)去執(zhí)行父類(lèi)的初始化程序,而是去執(zhí)行自己的初始化程序:def__init__(self): super(Child,self).__init__() print('Child')(1)子類(lèi)初始化程序的第1條語(yǔ)句:super(Child,self).__init__()。其含義是通過(guò)內(nèi)置函數(shù)super()調(diào)用名為_(kāi)_init__()的初始化程序。父類(lèi)有初始化程序,子類(lèi)也有初始化程序,這里是調(diào)用哪一個(gè)初始化程序呢?這將由內(nèi)置函數(shù)super()里給出的第1個(gè)參數(shù)“Child”來(lái)指明,即調(diào)用類(lèi)Child的父類(lèi)的初始化程序。于是,Python轉(zhuǎn)而去執(zhí)行父類(lèi)Parent的初始化程序:6.3.3內(nèi)置函數(shù)super()def__init__(self): self.parent='I\'mtheparent.' print('Parent')(2)子類(lèi)初始化程序的第2條語(yǔ)句:print('Child')。父類(lèi)的初始化程序的第1條語(yǔ)句是為變量self.parent賦初值“I’mtheparent”。第2條語(yǔ)句輸出信息“Parent”。于是,在圖6-12中輸出的第1條信息是“Parent”。含義是輸出信息“Child”。于是,在圖6-12里接著輸出了“Child”。至此,語(yǔ)句f_Child=Child()就分析并執(zhí)行完了。分析執(zhí)行語(yǔ)句“f_Child.fun('HelloPython!')”的情形。該語(yǔ)句的意思是由對(duì)象f_Child調(diào)用(自己的)方法fun(),傳遞的參數(shù)是“HelloPython!”。對(duì)象f_Child的方法fun()是:6.3.3內(nèi)置函數(shù)super()deffun(self,message): super(Child,self).fun(message) print('Childfunfuction') print(self.parent)共有3條語(yǔ)句,現(xiàn)在分析如下。01OPTION子類(lèi)fun()方法的第1條語(yǔ)句:super(Child,self).fun(message)。該語(yǔ)句是一條內(nèi)置函數(shù)super(),它要通過(guò)傳遞參數(shù)message去調(diào)用名為fun的方法。同樣地,父類(lèi)有名為fun的方法,子類(lèi)也有名為fun的方法。到底應(yīng)該調(diào)用哪一個(gè)將由內(nèi)置函數(shù)super()括號(hào)內(nèi)的第1個(gè)參數(shù)來(lái)定。很清楚,是要調(diào)用父類(lèi)Parent的方法fun()。于是,轉(zhuǎn)而去看父類(lèi)Parent的方法fun():deffun(self,message): print('%sfromparent'%message)6.3.3內(nèi)置函數(shù)super()02OPTION子類(lèi)方法fun()的第2條語(yǔ)句:print('Childfunfuction')。這條語(yǔ)句功能簡(jiǎn)單,就是輸出信息:Childfunfuction它的功能就是把message傳遞的信息輸出來(lái)?,F(xiàn)在message攜帶的信息是“HelloPython!”,因此在窗口里緊接著會(huì)輸出信息:HelloPython!Fromparent(見(jiàn)圖6-12輸出的第
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024高考地理一輪復(fù)習(xí)專練63河流流域的綜合開(kāi)發(fā)與治理含解析新人教版
- 2025高考數(shù)學(xué)考二輪專題突破練1 ??夹☆}點(diǎn)過(guò)關(guān)檢測(cè)-專項(xiàng)訓(xùn)練【含答案】
- 2024年清遠(yuǎn)職業(yè)技術(shù)學(xué)院高職單招語(yǔ)文歷年參考題庫(kù)含答案解析
- 預(yù)防校園性侵害工作制度
- 2024年浙江汽車(chē)職業(yè)技術(shù)學(xué)院高職單招語(yǔ)文歷年參考題庫(kù)含答案解析
- 2024年陜西地質(zhì)礦產(chǎn)局職工醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫(kù)頻考點(diǎn)附帶答案
- 2024年泰州職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)驗(yàn)歷年參考題庫(kù)(頻考版)含答案解析
- 2024年防城港務(wù)局職工醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫(kù)頻考點(diǎn)附帶答案
- 2024年阜新市婦產(chǎn)醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫(kù)頻考點(diǎn)附帶答案
- 2024年江西旅游商貿(mào)職業(yè)學(xué)院高職單招語(yǔ)文歷年參考題庫(kù)含答案解析
- 屠宰刀安全操作及保養(yǎng)規(guī)程
- 民航服務(wù)禮儀課件
- 公司供應(yīng)商大會(huì)策劃方案
- 云管理平臺(tái)運(yùn)營(yíng)面試題
- “簡(jiǎn)約與繁復(fù)”二元思辨【 審題立意+范文精評(píng) 】 語(yǔ)文高分寫(xiě)作 多元思辨
- 計(jì)算物理課件
- 集中供熱管網(wǎng)系統(tǒng)一次網(wǎng)的調(diào)節(jié)方法
- MRP、MPS計(jì)劃文檔教材
- 甲狀腺疾病護(hù)理查房課件
- 安全安全帶檢查記錄表
- Listen-to-this-3-英語(yǔ)高級(jí)聽(tīng)力-(整理版)
評(píng)論
0/150
提交評(píng)論