版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
面向?qū)ο蟪绦蛟O(shè)計(jì)08本章內(nèi)容面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn)類與對(duì)象構(gòu)造函數(shù)類成員的訪問(wèn)權(quán)限析構(gòu)函數(shù)類的組合多態(tài)性與運(yùn)算符重載繼承與派生應(yīng)用實(shí)例面向?qū)ο蟪绦蛟O(shè)計(jì)(ObjectOrientedProgramming,OOP)主要針對(duì)大型軟件設(shè)計(jì)提出,使得軟件設(shè)計(jì)更加靈活,能夠很好地支持代碼復(fù)用和設(shè)計(jì)復(fù)用,并且使得代碼具有更好的可讀性和可擴(kuò)展性。面向?qū)ο蟪绦蛟O(shè)計(jì)的一條基本原則是將多個(gè)能夠起到子程序作用的單元或?qū)ο蠼M合成計(jì)算機(jī)程序,這樣大大地降低了軟件開發(fā)的難度,使得編程就像搭積木一樣簡(jiǎn)單。面向?qū)ο蟪绦蛟O(shè)計(jì)的一個(gè)關(guān)鍵觀念是將數(shù)據(jù)以及對(duì)數(shù)據(jù)的操作封裝在一起,組成相互依存、不可分割的整體,通過(guò)對(duì)相同事物進(jìn)行抽象,得出共同的特征并形成類,面向?qū)ο蟪绦蛟O(shè)計(jì)的關(guān)鍵就是如何合理地定義和組織這些類以及類之間的關(guān)系。8.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn)抽象
面向?qū)ο蠓椒ㄖ械某橄螅菍?duì)具體的事物與其靜態(tài)及動(dòng)態(tài)狀態(tài)進(jìn)行分析,抽象出這一類事物的共有屬性,并加以描述。抽象的過(guò)程是對(duì)問(wèn)題從分析到認(rèn)知的過(guò)程。一般而言,抽象包括兩個(gè)部分,一個(gè)是對(duì)數(shù)據(jù)進(jìn)行抽象,即獲取靜態(tài)屬性;另一個(gè)是對(duì)行為進(jìn)行抽象,即獲取動(dòng)態(tài)屬性。如果要對(duì)學(xué)生的簡(jiǎn)單情況進(jìn)行登記,首先要對(duì)學(xué)生的共性進(jìn)行抽象,如果只需要登記學(xué)生的簡(jiǎn)單信息,靜態(tài)屬性有:ID,Name,Age,Phone_Namber,分別表示學(xué)生的學(xué)號(hào)、姓名、年齡、電話號(hào)碼等信息。這些數(shù)據(jù)能夠反映學(xué)生的靜態(tài)信息。但學(xué)生是可以運(yùn)動(dòng)的,不是山、房子等這類靜止不動(dòng)的物體,學(xué)生具有活動(dòng)的能力,所以除了靜態(tài)屬性外,還可以抽象出一些動(dòng)態(tài)屬性,如run、walk、eat等,分別對(duì)應(yīng)學(xué)生的跑、走、吃等能力,用代碼表示就是后面加上圓括號(hào),說(shuō)明這些動(dòng)態(tài)屬性是函數(shù),這些函數(shù)是學(xué)生行為的體現(xiàn)。一個(gè)事物能夠抽象出來(lái)的靜態(tài)屬性和動(dòng)態(tài)屬性有許多,但一個(gè)任務(wù)往往并不需要全部的屬性,要根據(jù)任務(wù)來(lái)選擇屬性,同一個(gè)事物任務(wù)不同往往選擇的屬性不同。8.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn)封裝封裝是將抽象得到靜態(tài)屬性(數(shù)據(jù))和動(dòng)態(tài)屬性(行為或方法)相結(jié)合,形成一個(gè)整體。從代碼上來(lái)說(shuō)就是將數(shù)據(jù)與對(duì)數(shù)據(jù)處理的函數(shù)結(jié)合起來(lái),形成“類”,而數(shù)據(jù)和對(duì)數(shù)據(jù)處理的函數(shù)則為類的成員,分別稱為類的成員數(shù)據(jù)和成員函數(shù)。一般情況下類外的代碼不能直接訪問(wèn)類中的成員數(shù)據(jù),如果類外的代碼要訪問(wèn)類中的成員數(shù)據(jù),只能通過(guò)類的成員函數(shù),也就是說(shuō)類的成員函數(shù)是類與類外代碼聯(lián)系的接口。將數(shù)據(jù)與行為封裝為一個(gè)可重用的代碼塊,可以有效的降低代碼復(fù)雜度。8.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn)繼承現(xiàn)實(shí)世界中的事物具有特殊與一般的關(guān)系。例如,動(dòng)物有名稱、年齡、體重等屬性,并具有吃、排泄等行為。動(dòng)物按生活環(huán)境可以分為:陸生動(dòng)物、水生動(dòng)物和兩棲動(dòng)物。陸生動(dòng)物具有在陸地生活的特性,大多數(shù)都呼吸空氣,獅子、松鼠、老鼠等都是陸生動(dòng)物。獅子是肉食性動(dòng)物、體型大、攻擊性強(qiáng)、奔跑速度快等特點(diǎn)。松鼠居住于樹上,個(gè)頭小,是草食性動(dòng)物。老鼠是雜食性動(dòng)物,個(gè)頭小,鉆洞能力強(qiáng)。動(dòng)物類、陸生動(dòng)物類與獅子類、松鼠類、老鼠類就屬于一般與特殊的關(guān)系,獅子類、松鼠類、老鼠類繼承了陸生動(dòng)物的特性,但又有各自的特性。陸生動(dòng)物繼承了動(dòng)物類的特點(diǎn),但又有呼吸空氣等特性。繼承就是解決一般與特殊的關(guān)系,描述特殊類之間的一些共享的共性。Python語(yǔ)言中提供了類的繼承機(jī)制,允許程序員在保持原有類特性的基礎(chǔ)上,派生出新的屬性與行為。8.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn)多態(tài)多態(tài)是與我們生活中的人類思維方式很類似,如生活中我們常說(shuō)的“駕駛”,“駕駛”是個(gè)行為,但對(duì)于不同的事物“駕駛”的行為和規(guī)則是完全不一樣的,如“駕駛小汽車”、“駕駛直升機(jī)”、“駕駛坦克”等等,都是“駕駛”行為,但操作步驟完全不同。廣義上來(lái)說(shuō),多態(tài)性是一段程序能夠處理多種類型對(duì)象的能力。Python程序中,表示不同類型的對(duì)象接收同樣的消息時(shí)出現(xiàn)了不同的行為,即同樣的運(yùn)算被不同的對(duì)象調(diào)用時(shí)產(chǎn)生不一樣的行為。比如+運(yùn)算,對(duì)于字符串表示字符串連接,對(duì)于數(shù)字類型表示求和。8.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本特點(diǎn)8.2類與對(duì)象類的定義對(duì)象類的成員函數(shù)類的成員數(shù)據(jù)面向?qū)ο蟮木幊趟枷胧菍⑹挛锍橄鬄轭?,以類為程序模塊,這樣程序模塊的獨(dú)立性、數(shù)據(jù)的安全性就有良好的保障。類是面向?qū)ο蟪绦蛟O(shè)計(jì)方法的核心,利用類可以實(shí)現(xiàn)對(duì)數(shù)據(jù)的封裝和隱藏。Python中,可以使用class關(guān)鍵字定義類,然后通過(guò)定義的類創(chuàng)建實(shí)例對(duì)象。類定義的語(yǔ)法格式如下:class類名:'''類說(shuō)明'''
類體類名的首字母一般大寫,類名的命名風(fēng)格在整個(gè)系統(tǒng)中最好統(tǒng)一,這對(duì)于團(tuán)隊(duì)合作開發(fā)的系統(tǒng)十分重要。類體就是類的內(nèi)部實(shí)現(xiàn),類的實(shí)現(xiàn)語(yǔ)句必須在左方留有空格并靠左對(duì)齊。定義一個(gè)類,可以理解為在程序中增加了一個(gè)新的特殊數(shù)據(jù)類型。8.2.1類的定義上面代碼創(chuàng)建了一個(gè)Circle類,類實(shí)現(xiàn)中只有一條pass語(yǔ)句,pass類似于空語(yǔ)句,也就是這個(gè)Circle類體實(shí)現(xiàn)中不做任何操作。上面代碼創(chuàng)建了一個(gè)Point類,類體中有個(gè)print輸出命令。8.2.1類的定義classCircle:'''圓類'''passclassPoint:'''點(diǎn)類'''
print("Thisisapoint")可以把一個(gè)類理解為一個(gè)特殊的數(shù)據(jù)類型。int、float等是Python的基礎(chǔ)數(shù)據(jù)類型,可以通過(guò)賦值來(lái)創(chuàng)建相應(yīng)的變量,用來(lái)存儲(chǔ)數(shù)據(jù)。與基礎(chǔ)類型一樣,如果定義了一個(gè)類,則可以創(chuàng)建這個(gè)類的特殊變量,這個(gè)特殊變量稱為該類的對(duì)象,創(chuàng)建對(duì)象的過(guò)程稱為類的實(shí)例化。如果說(shuō)變量是基礎(chǔ)數(shù)據(jù)類型的實(shí)例,則對(duì)象就是類的實(shí)例。創(chuàng)建對(duì)象(類的實(shí)例)的語(yǔ)法形式如下:8.2.2對(duì)象對(duì)象名=類名()下面代碼創(chuàng)建并使用了一個(gè)Circle類:第4行代碼創(chuàng)建了一個(gè)名為c的Circle對(duì)象。由于Circle類體中只有注釋語(yǔ)句和一個(gè)空語(yǔ)句pass,因此Circle類體中沒(méi)有做任何操作,這樣其創(chuàng)建的對(duì)象c內(nèi)容也是空。8.2.2對(duì)象1234classCircle:'''圓類'''passc=Circle()上面代碼創(chuàng)建了一個(gè)Point類,并在第4、5行創(chuàng)建了2個(gè)Point類的對(duì)象p1和p2。程序從第1行代碼開始執(zhí)行,首先運(yùn)行的是類Point的聲明,程序進(jìn)入類Point的類體,執(zhí)行第3行print("Thisisapoint"),在終端輸出了"Thisisapoint"。然后依次執(zhí)行第4行、第5行,實(shí)例化Point類,創(chuàng)建p1和p2對(duì)象,p1、p2都是空對(duì)象。所以終端輸出"Thisisapoint"并不是指p1、p2對(duì)象內(nèi)含print語(yǔ)句并執(zhí)行了,而是程序在掃描類Point定義的時(shí)候執(zhí)行了print輸出語(yǔ)句,p1和p2對(duì)象與第3行print語(yǔ)句沒(méi)有聯(lián)系。8.2.2對(duì)象12345classPoint:'''點(diǎn)類'''print("Thisisapoint")p1=Point()p2=Point()>>>
Thisisapoint類的第一個(gè)特性就是將客觀事物的靜態(tài)屬性(數(shù)據(jù))和動(dòng)態(tài)屬性(行為或方法)提取出來(lái)并組合為一個(gè)不可分割的整體,實(shí)現(xiàn)面向?qū)ο蟪绦蛟O(shè)計(jì)的基礎(chǔ)。成員函數(shù)的實(shí)現(xiàn)成員函數(shù)的定義與普通函數(shù)定義的語(yǔ)法形式類似,區(qū)別是成員函數(shù)的形參列表前面多了個(gè)self參數(shù)。如果是無(wú)參成員函數(shù),則在定義成員函數(shù)時(shí)參數(shù)列表為空,但self仍然保留。8.2.3類的成員函數(shù)def函數(shù)名(self[,參數(shù)列表])函數(shù)體[return表達(dá)式]【例8-1】成員函數(shù)定義舉例:程序執(zhí)行第1行,創(chuàng)建一個(gè)Point類,并在Point類中定義了一個(gè)函數(shù)m_print。第4行和第5行是創(chuàng)建Point類的對(duì)象p1和p2。類中只是定義了成員函數(shù),而執(zhí)行成員函數(shù)則要靠類的實(shí)例(對(duì)象)來(lái)調(diào)用,調(diào)用成員函數(shù)的語(yǔ)法為:在定義類成員函數(shù)時(shí),如果需要在該成員函數(shù)中調(diào)用類的另外一個(gè)成員函數(shù),調(diào)用語(yǔ)法為:8.2.3類的成員函數(shù)12345classPoint:defm_print(self):print("Thisisapoint")p1=Point()p2=Point()對(duì)象名.成員函數(shù)名(參數(shù)列表)self.成員函數(shù)名(參數(shù)列表)>>>p1.m_print()Thisisapoint>>>p2.m_print()Thisisapoint【例8-2】成員函數(shù)調(diào)用舉例。第4行代碼定義了一個(gè)Point類的成員函數(shù)m_fun,該函數(shù)體中調(diào)用了m_print成員函數(shù)。所以在第10行對(duì)象p2調(diào)用成員函數(shù)m_fun時(shí),會(huì)先執(zhí)行第5行代碼調(diào)用m_print函數(shù),輸出"Thisisapoint",然后執(zhí)行第6行代碼輸出"Test"。8.2.3類的成員函數(shù)12345678910classPoint:defm_print(self):print("Thisisapoint")defm_fun(self):
self.m_print()#調(diào)用其它成員函數(shù)print("Test")p1=Point()p2=Point()p1.m_print()p2.m_fun()>>>
ThisisapointThisisapointTest類的成員函數(shù)與普通類外函數(shù)的使用相差不大,也支持默認(rèn)參數(shù)值。【例8-3】帶默認(rèn)值參數(shù)的成員函數(shù)舉例。8.2.3類的成員函數(shù)12345678910classPoint:defm_print(self):print("Thisisapoint")defm_fun(self,s="Test"):self.m_print()print(s)p1=Point()p1.m_print()p1.m_fun()p1.m_fun("Message")>>>
ThisisapointThisisapointTestThisisapointMessage類的成員除了動(dòng)態(tài)屬性外還有靜態(tài)屬性,動(dòng)態(tài)屬性用成員函數(shù)來(lái)實(shí)現(xiàn),靜態(tài)屬性則用成員數(shù)據(jù)來(lái)實(shí)現(xiàn)。Python的成員數(shù)據(jù)包括類屬性和實(shí)例(對(duì)象)屬性兩種。類屬性是定義類時(shí)在成員函數(shù)外定義的變量,也可以是在類成員函數(shù)內(nèi)或類外用“類名.屬性名”創(chuàng)建的變量。該變量不屬于某個(gè)對(duì)象,屬于這個(gè)類,類屬性則是所有對(duì)象共享。類屬性可以用對(duì)象名.類屬性名或類名.類屬性名在類的定義外部進(jìn)行調(diào)用。實(shí)例屬性是在成員函數(shù)內(nèi)定義的變量,或在類外用“對(duì)象名.屬性名”創(chuàng)建的變量。每個(gè)對(duì)象的實(shí)例屬性都是相互獨(dú)立的。實(shí)例屬性可以用“self.屬性名”在成員函數(shù)中創(chuàng)建,在類定義外也可以用“對(duì)象名.屬性名”為該對(duì)象增加實(shí)例屬性。8.2.4類的成員數(shù)據(jù)【例8-4】類屬性舉例。8.2.4類的成員數(shù)據(jù)1234567891011121314classPoint:x=0#定義Point類屬性z=1#定義Point類屬性#Point.k=10#報(bào)錯(cuò),因?yàn)镻oint還沒(méi)有定義defsetXY(self,x,y):Point.x=x#修改Point類屬性x的值Point.y=y#定義Point類屬性Point.w=2#定義Point類屬性defgetX(self):returnPoint.xdefgetY(self):returnPoint.ydefgetZ(self):returnPoint.z151617181920212223242526p1=Point()p2=Point()p1.setXY(5,6)Point.v=22#類外創(chuàng)建Point類屬性print("p1.x=",p1.getX(),",p1.y=",p1.y)print("p1.z=",p1.getZ(),",p1.w=",p1.w,",p1.v=",p1.v)print("p2.x=",p2.getX(),",p2.y=",p2.y)print("p2.z=",p2.getZ(),",p2.w=",p2.w,",p2.v=",p2.v)#print("Point.x=",Point.getX())#報(bào)錯(cuò),getX是成員函數(shù)#print("Point.z=",Point.getZ())#報(bào)錯(cuò),getZ是成員函數(shù)print("Point.y=",Point.y)print("Point.w=",Point.w,",Point.v=",Point.v)>>>
p1.x=5,p1.y=6p1.z=1,p1.w=2,p1.v=22p2.x=5,p2.y=6p2.z=1,p2.w=2,p2.v=22Point.y=6Point.w=2,Point.v=22【例8-5】實(shí)例屬性舉例。8.2.4類的成員數(shù)據(jù)1234567891011classPoint:#self.z=1#報(bào)錯(cuò),實(shí)例屬性必須在函數(shù)內(nèi)定義defsetXY(self,x,y):self.x=xu=y#創(chuàng)建局部變量udefgetX(self):returnself.xdefeditX(self,x):self.x=xp1=Point()p2=Point()12131415161718192021p1.setXY(5,9)p2.setXY(44,77)Point.v=22#添加類屬性print("p1.x=",p1.getX(),",p2.x=",p2.getX())p1.editX(10)print(p1.x,p2.x)#print(Point.x)#報(bào)錯(cuò),x不是類屬性p1.w=2#給對(duì)象p1添加實(shí)例屬性print(p1.w)#print(p2.w)#報(bào)錯(cuò),p2中沒(méi)有w成員變量>>>
p1.x=5,p2.x=4410442關(guān)于類屬性和實(shí)例屬性,總計(jì)如下:類屬性屬于類本身,可以通過(guò)類名進(jìn)行訪問(wèn)或修改,如Point.x類屬性也可以被類的所有實(shí)例對(duì)象訪問(wèn)或修改,如p1.x在類定義之后,可以通過(guò)類名動(dòng)態(tài)添加類屬性,新增的類屬性被類和所有實(shí)例共有類的實(shí)例屬性只能通過(guò)類名的對(duì)象訪問(wèn)在類的對(duì)象生成后,可以動(dòng)態(tài)添加實(shí)例屬性,但這些添加的實(shí)例屬性只屬于該對(duì)象8.2.4類的成員數(shù)據(jù)Python允許在類的定義外為類和對(duì)象增加新的數(shù)據(jù)和行為,這稱為混入機(jī)制。這種混入機(jī)制在大型項(xiàng)目的開發(fā)中會(huì)非常方便和實(shí)用。在類定義外為Point類增加類屬性v:Point.v=22為Point類對(duì)象p1增加實(shí)例屬性w:p1.w=2,而同樣的Point類對(duì)象p2卻沒(méi)有增加w這個(gè)實(shí)例屬性。這兩種動(dòng)態(tài)增加成員數(shù)據(jù)的方法都屬于混入機(jī)制。行為是一個(gè)動(dòng)態(tài)屬性,而函數(shù)是行為的代碼實(shí)現(xiàn),在Python中還可以把函數(shù)增加到實(shí)例里面,可以采用type.MethodType()把獨(dú)立定義的外部函數(shù)變?yōu)橐粋€(gè)對(duì)象的成員函數(shù),但需要導(dǎo)入types模塊。8.2.4類的成員數(shù)據(jù)【例8-6】成員函數(shù)的混入機(jī)制舉例。8.2.4類的成員數(shù)據(jù)123456789101112131415classPoint:defsetX(self,x):self.x=xp1=Point()p2=Point()p1.setX(5)p2.setX(10)importtypes#導(dǎo)入types模塊deffun(self,y):self.y=yp1.setY=types.MethodType(fun,p1)p1.setY(6)print(p1.x,p1.y)#p2.setY(11)#報(bào)錯(cuò)#print(p2.x,p2.y)#報(bào)錯(cuò)>>>
56類與對(duì)象的關(guān)系就相當(dāng)于基本數(shù)據(jù)類型與變量的關(guān)系,是類型與實(shí)例的關(guān)系。同屬一個(gè)類的多個(gè)對(duì)象之間的區(qū)別在兩個(gè)方面一個(gè)是對(duì)象名不同,另一個(gè)是對(duì)象的成員數(shù)據(jù)值不同。Python中通過(guò)“=”直接創(chuàng)建變量并對(duì)變量賦初值,而在創(chuàng)建類的對(duì)象時(shí),也可以在創(chuàng)建對(duì)象的同時(shí)用數(shù)據(jù)對(duì)對(duì)象賦初值。在定義對(duì)象的時(shí)候?qū)ζ涑蓡T數(shù)據(jù)進(jìn)行設(shè)置,稱為對(duì)象的初始化。Python語(yǔ)言可以通過(guò)賦值來(lái)創(chuàng)建一個(gè)變量并對(duì)變量賦初值,創(chuàng)建一個(gè)變量意味著程序要為變量在內(nèi)存中創(chuàng)建一定的空間,并寫入變量的初始值。對(duì)象的創(chuàng)建,系統(tǒng)需要為對(duì)象創(chuàng)建一定的內(nèi)存空間。由于對(duì)象遠(yuǎn)比基礎(chǔ)類型的變量要復(fù)雜,它除了具有成員函數(shù)還有成員數(shù)據(jù),在創(chuàng)建對(duì)象并對(duì)對(duì)象進(jìn)行賦初值時(shí),系統(tǒng)是不知道如何產(chǎn)生代碼來(lái)實(shí)現(xiàn)對(duì)成員數(shù)據(jù)的賦值,這就需要程序員來(lái)自己撰寫初始化程序。對(duì)象在創(chuàng)建時(shí),利用特殊值對(duì)實(shí)例屬性進(jìn)行賦初值的過(guò)程,是通過(guò)構(gòu)造函數(shù)實(shí)現(xiàn)的。8.3構(gòu)造函數(shù)構(gòu)造函數(shù)是類的一個(gè)成員函數(shù),除了具有一般成員函數(shù)的特性外,還有一些特殊的性質(zhì)。構(gòu)造函數(shù)名為__init__,并且沒(méi)有返回值。只要類中有了構(gòu)造函數(shù),在創(chuàng)建新對(duì)象時(shí)會(huì)自動(dòng)調(diào)用并運(yùn)行構(gòu)造函數(shù)的代碼實(shí)現(xiàn)實(shí)例屬性賦值。一個(gè)類有且只有一個(gè)構(gòu)造函數(shù)。調(diào)用時(shí)無(wú)需提供參數(shù)的構(gòu)造函數(shù)稱為默認(rèn)構(gòu)造函數(shù)。如果類中沒(méi)有手動(dòng)定義構(gòu)造函數(shù),Pyhon會(huì)自動(dòng)生成一個(gè)隱含的默認(rèn)構(gòu)造函數(shù),該構(gòu)造函數(shù)的參數(shù)列表和函數(shù)體都為空。但如果類中定義了構(gòu)造函數(shù)(無(wú)論是否有參數(shù)),Python便不會(huì)再為該類生成一個(gè)隱含的構(gòu)造函數(shù)。定義構(gòu)造函數(shù)的語(yǔ)法為:構(gòu)造函數(shù)的使用8.3構(gòu)造函數(shù)def__init__(self,[參數(shù)列表]):
函數(shù)體對(duì)象名=類名([參數(shù)列表])【例8-7】構(gòu)造函數(shù)舉例。8.3構(gòu)造函數(shù)1234567891011classPoint:def__init__(self,x,y): self.x=x self.y=ydefgetX(self): returnself.xdefgetY(self): returnself.yp1=Point(5,10)print(p1.getX(),p1.getY())#p2=Point()#報(bào)錯(cuò)>>>510【例8-8】構(gòu)造函數(shù)舉例。8.3構(gòu)造函數(shù)1234567891011classPoint:def__init__(self,x=0,y=0): self.x=x self.y=ydefsetXY(self,x,y): self.x=x self.y=ydefgetX(self): returnself.xdefgetY(self): returnself.y1213141516171819202122p1=Point()p2=Point(5,10)print("p1.x=",p1.getX(),end=',')print("p1.y=",p1.y)print("p2.x=",p2.getX(),end=',')print("p2.y=",p2.y)p1.setXY(25,30)print("p1.x=",p1.getX(),end=',')print("p1.y=",p1.getY())print(p2.x)print(p1.x)>>>p1.x=0,p1.y=0p2.x=5,p2.y=10p1.x=25,p1.y=30525【例8-9】創(chuàng)建一個(gè)矩陣類,矩形類有長(zhǎng)、寬屬性,有一個(gè)成員函數(shù)來(lái)求面積,創(chuàng)建矩陣類對(duì)象時(shí),有構(gòu)造函數(shù)給長(zhǎng)、寬賦0值。現(xiàn)在有一個(gè)長(zhǎng)、寬都為20的正方形和一個(gè)長(zhǎng)、寬分別為3、5的矩形?,F(xiàn)編程通過(guò)矩形類來(lái)求正方形和矩形的面積。8.3構(gòu)造函數(shù)12345678910classRect:def__init__(self,l=0,w=0):self.l=lself.w=wdefgetArea(self):returnself.l*self.wrect1=Rect(20,20)print("rect1=",rect1.getArea())rect2=Rect(3,5)print("rect2=",rect2.getArea())>>>
rect1=400rect2=15類的成員包括成員數(shù)據(jù)和對(duì)成員數(shù)據(jù)操作的成員函數(shù),它們分別描述事物的靜態(tài)屬性和動(dòng)態(tài)行為,是不可分割。類成員的訪問(wèn)權(quán)限有三種:公有成員、私有成員、保護(hù)型成員。公有成員是類對(duì)外的接口,類中除了私有成員、保護(hù)型成員和系統(tǒng)定義的特殊成員外都是公有成員,一般將對(duì)數(shù)據(jù)的操作設(shè)為公有成員,公有成員可以通過(guò)對(duì)象名直接調(diào)用。私有成員是以雙下劃線開頭的屬性或方法,如:__hour、__minute、__second。正常情況下私有成員只允許在類定義中被本類的其它成員訪問(wèn),類定義外對(duì)私有成員的訪問(wèn)都是非法的。但在Python中可以通過(guò)“類的對(duì)象名._類名__成員名”方式來(lái)強(qiáng)行訪問(wèn)私有成員“__成員名”,這種破壞類封裝特性的方式不建議使用。私有成員被隱藏在類中,保護(hù)了數(shù)據(jù)的安全性,所以一般而言,類的數(shù)據(jù)成員都應(yīng)該被設(shè)置為私有成員。保護(hù)型成員是以單下劃線開頭的屬性或方法,如:_x、_y。保護(hù)型成員在類定義中可以被本類的其它成員訪問(wèn),類定義外也可以被直接訪問(wèn)。8.4類成員的訪問(wèn)權(quán)限【例8-10】類成員的訪問(wèn)權(quán)限舉例。8.4類成員的訪問(wèn)權(quán)限12345678910111213141516171819classPoint:def__init__(self,a=0,b=0,c=0):Point.__x=a#私有成員Point._y=b#保護(hù)成員Point.z=cdefgetX(self):returnPoint.__xdefgetY(self):returnPoint._yp1=Point()print(p1.getX(),p1.getY(),Point.z)p2=Point(3,9,15)#print(p1.__x)#報(bào)錯(cuò),私有成員無(wú)法在類外訪問(wèn)#print(Point.__x)#報(bào)錯(cuò),私有成員無(wú)法在類外訪問(wèn)print(p1.getX(),p1.getY(),Point.z)print(p2.getX(),p2.getY(),Point.z)print(p1._y,p2._y,Point._y)print(p2.z,p1.z,Point.z)#可以直接訪問(wèn)print(p2._Point__x)#強(qiáng)行訪問(wèn)類p2的私有成員__x>>>000391539159991515153
【例8-11】類成員的訪問(wèn)權(quán)限舉例。8.4類成員的訪問(wèn)權(quán)限1234567891011121314151617classPoint:def__init__(self,a=0,b=0,c=0):self.__x=aself._y=bself.z=cdefgetX(self):returnself.__xdefgetY(self):returnself._yp1=Point()print(p1.getX(),p1.getY(),p1.z)p2=Point(3,9,15)print(p1.getX(),p1.getY(),p1.z)print(p2.getX(),p2.getY(),p2.z)#print(p1.__x,p2.__x)#報(bào)錯(cuò)print(p1._y,p2._y)#可以直接訪問(wèn)print(p2._Point__x)#強(qiáng)行訪問(wèn)類p2的私有成員__x>>>0000003915093【例8-12】類成員的訪問(wèn)權(quán)限舉例。8.4類成員的訪問(wèn)權(quán)限123456789101112131415161718classA:def__init__(self,val1=0,val2=0):self._val1=val1#protectedself.__val2=val2#privatedefsetval(self,a,b):self._val1=aself.__val2=bdefaddval(self,val1,val2):self._val3=val1self.__val4=val2def__show(self):print(self._val1)print(self.__val2)defshow(self):print(self._val1)print(self.__val2)print(self._val3)print(self.__val4)192021222324252627a=A()b=A(1,2)print(a._val1)a.setval(2,3)a.addval(5,10)a.show()#b.show()#報(bào)錯(cuò)#a.__show()#報(bào)錯(cuò)print(a)>>>023510<__main__.Aobjectat0x000002A6E5804888>【例8-13】定義并實(shí)現(xiàn)一個(gè)平面點(diǎn)類Point,有x方向、y方向兩個(gè)坐標(biāo)值,有成員函數(shù)修改x、y坐標(biāo)值。8.4類成員的訪問(wèn)權(quán)限12345678910111213classPoint:def__init__(self,x=0,y=0):self.__x=xself.__y=ydefset(self,x,y):self.__x=xself.__y=ydefgetX(self):returnself.__xdefgetY(self):returnself.__ydefshow(self):print('(',self.__x,',',self.__y,')')14151617181920p1=Point(3,4)p2=Point(5,6)p1.show()p2.show()p2.set(7,9)p2.show()print((p1.getX()-p2.getX())**2+(p1.getY()-p2.getY())**2)>>>(3,4)(5,6)(7,9)41【例8-14】定義并實(shí)現(xiàn)一個(gè)矩形類,有長(zhǎng)、寬兩個(gè)屬性,有成員函數(shù)計(jì)算矩陣的面積。8.4類成員的訪問(wèn)權(quán)限12345678910111213classRect:def__init__(self,l=0,w=0):self.__l=lself.__w=wdefsetLW(self,l,w):self.__l=lself.__w=wdefgetL(self):returnself.__ldefgetW(self):returnself.__wdefcalArea(self):returnself.__w*self.__l>>>
Area_rect1=0Area_rect2=24Area_rect1=200141516171819rect1=Rect()print("Area_rect1=",rect1.calArea())rect2=Rect(4,6)print("Area_rect2=",rect2.calArea())rect1.setLW(10,20)print("Area_rect1=",rect1.calArea())【例8-15】定義復(fù)數(shù)類Comp,有實(shí)部和虛部?jī)蓚€(gè)屬性,有成員函數(shù)set()修改復(fù)數(shù)實(shí)部和虛部的值,有成員函數(shù)mod計(jì)算復(fù)數(shù)的模平方,有成員函數(shù)add()、minus()實(shí)現(xiàn)與其它復(fù)數(shù)對(duì)象相加和相減,有成員函數(shù)show()輸出該復(fù)數(shù)。8.4類成員的訪問(wèn)權(quán)限12345678910111213141516classComp:def__init__(self,r=0,i=0):self.__r=rself.__i=idefset(self,r,i):self.__r=rself.__i=idefmod(self):returnself.__r**2+self.__i**2defgetR(self):returnself.__rdefgetI(self):returnself.__idefadd(self,c):self.__r+=c.__rself.__i+=c.__i171819202122232425262728293031323334defminus(self,c):self.__r-=c.__rself.__i-=c.__idefshow(self):print(self.__r,'+',self.__i,'i')c1=Comp()c2=Comp()c3=Comp()c1.set(3,4)c2.set(5,10)c1.show()c2.show()print(c1.mod())c2.add(c1)c3=c2c3.show()c3.minus(c1)c3.show()>>>3+4i5+10i258+14i5+10iPython中類的析構(gòu)函數(shù)是__del__(),用于實(shí)現(xiàn)銷毀類的實(shí)例所需的操作,一般用來(lái)釋放對(duì)象占用的資源(如打開的文件、網(wǎng)絡(luò)連接等),在Python刪除對(duì)象和收回對(duì)象空間時(shí)被自動(dòng)調(diào)用和執(zhí)行。如果用戶沒(méi)有編寫析構(gòu)函數(shù),Python將提供一個(gè)默認(rèn)的析構(gòu)函數(shù)進(jìn)行必要的清理工作。8.5析構(gòu)函數(shù)【例8-16】析構(gòu)函數(shù)舉例。8.5析構(gòu)函數(shù)123456789101112131415161718classPoint:def__init__(self,x=0,y=0):self.__x=xself.__y=ydefgetX(self):returnself.__xdefgetY(self):returnself.__ydefshow(self):print('(',self.__x,',',self.__y,')')def__del__(self):print("Destruction")p1=Point(3,4)p2=Point(5,6)p2.__del__()p2.show()delp1delp2>>>Destruction(5,6)DestructionDestruction類與對(duì)象的關(guān)系就如基礎(chǔ)類型與變量的關(guān)系,可以把對(duì)象看作一個(gè)特殊的變量?;A(chǔ)類型的變量可以作為類的數(shù)據(jù)成員,類的對(duì)象也是可以作為另一個(gè)類的數(shù)據(jù)成員,這種類中的數(shù)據(jù)成員是另一個(gè)類的對(duì)象情況,我們稱之為類的組合。類的組合可以在已有抽象的基礎(chǔ)上實(shí)現(xiàn)更復(fù)雜的抽象。8.6類的組合【例8-17】類的組合舉例。8.6類的組合1234567891011121314151617classPoint: def__init__(self,x,y): self.__x=x self.__y=y defgetX(self): returnself.__x defgetY(self): returnself.__yclassLine: def__init__(self,p1,p2): self.__p1=p1 self.__p2=p2 x=p1.getX()-p2.getX() y=p1.getY()-p2.getY() self.__len=(x*x+y*y)**(1/2) defgetLen(self): returnself.__len>>>5.018192021p1=Point(1,2)p2=Point(4,6)l=Line(p1,p2)print(l.getLen())面向?qū)ο蟪绦蛟O(shè)計(jì)中的封裝特性通過(guò)類的成員變量和成員函數(shù)來(lái)實(shí)現(xiàn),多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的第二個(gè)特性,多態(tài)是指不同類型的對(duì)象接收同樣的消息時(shí)出現(xiàn)了不同的行為。也就是同樣的運(yùn)算被不同的對(duì)象調(diào)用時(shí)產(chǎn)生不一樣的行為,最簡(jiǎn)單的例子就是算術(shù)運(yùn)算符,同樣的加號(hào)、減號(hào),被不同的類型數(shù)據(jù)如整型、浮點(diǎn)型調(diào)用時(shí),會(huì)產(chǎn)生不一樣的結(jié)果整型相加、減得到的結(jié)果是整型浮點(diǎn)型相加、減得到的結(jié)果是有小數(shù)點(diǎn)的浮點(diǎn)型整型和浮點(diǎn)型相加則會(huì)先將整型隱式轉(zhuǎn)為浮點(diǎn)型再求加、減,最后得到的結(jié)果是浮點(diǎn)型。這就是典型的多態(tài)性,同樣的運(yùn)算符被不同類型的數(shù)據(jù)調(diào)用,會(huì)根據(jù)不同的數(shù)據(jù)類型進(jìn)行不一樣操作過(guò)程,運(yùn)算符的多態(tài)性我們稱之為運(yùn)算符重載。Python中運(yùn)算符的操作對(duì)象一般都是基礎(chǔ)數(shù)據(jù)類型,如整型、浮點(diǎn)型、字符串、列表等。而對(duì)于新創(chuàng)建的數(shù)據(jù)類型,這些運(yùn)算符都是不支持的。8.7多態(tài)性與運(yùn)算符重載
8.7多態(tài)性與運(yùn)算符重載123456789classComplex: def__init__(self,r=0,i=0): self.__r=r self.__i=i defshow(self): print(self.__r,'+',self.__i,'i')c1=Complex(1,2)c2=Complex(3,6)print(c1+c2)運(yùn)行結(jié)果:TypeError:unsupportedoperandtype(s)for+:'Complex'and'Complex'上面程序中由于c1和c2是新定義類Complex的兩個(gè)對(duì)象,Python不清楚如何將一個(gè)Complex對(duì)象與另外一個(gè)Complex對(duì)象相加,也就無(wú)法生成實(shí)現(xiàn)c1+c2的代碼,程序報(bào)錯(cuò)。如果創(chuàng)建了一個(gè)新類型,要想讓Python的運(yùn)算符支持新類型的對(duì)象,則用戶必須自己手動(dòng)定義相應(yīng)的特殊函數(shù)來(lái)實(shí)現(xiàn),這就是運(yùn)算符重載。Python中除了構(gòu)造函數(shù)和析構(gòu)函數(shù)外,還有大量的特殊方法支持更多的功能,運(yùn)算符重載就是通過(guò)在類中重新定義特殊函數(shù)來(lái)實(shí)現(xiàn)的。通過(guò)在自定義類中重寫特殊函數(shù)能夠增加類的基礎(chǔ)類型運(yùn)算功能。8.7多態(tài)性與運(yùn)算符重載
8.7多態(tài)性與運(yùn)算符重載函數(shù)功能說(shuō)明__new__()類的靜態(tài)方法,用于確定是否要?jiǎng)?chuàng)建對(duì)象__init__()構(gòu)造方法,創(chuàng)建對(duì)象時(shí)自動(dòng)調(diào)用__del__()析構(gòu)方法,釋放對(duì)象時(shí)自動(dòng)調(diào)用__add__()、__radd__()左+、右+__sub__()-__mul__()*__truediv__()/__floordiv__()//__mod__()%__pow__()**__eq__()、__ne__()、__lt__()、__le__()、__gt__()、__ge__()==、!=、<、<=、>、>=__lshift__()、__rshift__()<<、>>__and__()、__or__()、__invert__()、__xor__()&、|、~、^__iadd__()、__isub__()+=、-=,很多其他運(yùn)算符也有與之對(duì)應(yīng)的復(fù)合賦值運(yùn)算符
8.7多態(tài)性與運(yùn)算符重載__pos__()一元運(yùn)算符+,正號(hào)__neg__()一元運(yùn)算符-,負(fù)號(hào)__contains__()與成員測(cè)試運(yùn)算符in對(duì)應(yīng)__radd__()、__rsub__反射加法、反射減法,一般與普通加法和減法具有相同的功能,但操作數(shù)的位置或順序相反,很多其他運(yùn)算符也有與之對(duì)應(yīng)的反射運(yùn)算符__abs__()與內(nèi)置函數(shù)abs()對(duì)應(yīng)__bool__()與內(nèi)置函數(shù)bool()對(duì)應(yīng),要求該方法必須返回True或False__bytes__()與內(nèi)置函數(shù)bytes()對(duì)應(yīng)__complex__()與內(nèi)置函數(shù)complex()對(duì)應(yīng),要求該方法必須返回復(fù)數(shù)__dir__()與內(nèi)置函數(shù)dir()對(duì)應(yīng)__divmod__()與內(nèi)置函數(shù)divmod()對(duì)應(yīng)__float__()與內(nèi)置函數(shù)float()對(duì)應(yīng),要求該該方法必須返回實(shí)數(shù)__int__()與內(nèi)置函數(shù)int()對(duì)應(yīng),要求該方法必須返回整數(shù)__len__()與內(nèi)置函數(shù)len()對(duì)應(yīng)__next__()與內(nèi)置函數(shù)next()對(duì)應(yīng)
8.7多態(tài)性與運(yùn)算符重載__reduce__()提供對(duì)reduce()函數(shù)的支持__reversed__()與內(nèi)置函數(shù)reversed()對(duì)應(yīng)__round__()對(duì)內(nèi)置函數(shù)round()對(duì)應(yīng)__str__()與內(nèi)置函數(shù)str()對(duì)應(yīng),要求該方法必須返回str類型的數(shù)據(jù)。__repr__()打印、轉(zhuǎn)換,要求該方法必須返回str類型的數(shù)據(jù)。直接使用該類對(duì)象作為表達(dá)式來(lái)查看對(duì)象的值__getitem__()按照索引獲取值__setitem__()按照索引賦值__delattr__()刪除對(duì)象的指定屬性__getattr__()獲取對(duì)象指定屬性的值,對(duì)應(yīng)成員訪問(wèn)運(yùn)算符“.”__getattribute__()獲取對(duì)象指定屬性的值,如果同時(shí)定義了該方法與__getattr__(),那么__getattr__()將不會(huì)被調(diào)用,除非在__getattribute__()中顯式調(diào)用__getattr__()或者拋出AttributeError異常__setattr__()設(shè)置對(duì)象指定屬性的值__base__該類的基類__class__返回對(duì)象所屬的類__dict__對(duì)象所包含的屬性與值的字典__subclasses__()返回該類的所有子類__call__()包含該特殊方法的類的實(shí)例可以像函數(shù)一樣調(diào)用__get__()定義了這三個(gè)特殊方法中任何一個(gè)的類稱作描述符(descriptor),描述符對(duì)象一般作為其他類的屬性來(lái)使用,這三個(gè)方法分別在獲取屬性、修改屬性值或刪除屬性時(shí)被調(diào)用__set__()__delete__()如果用print函數(shù)輸出一個(gè)對(duì)象,會(huì)顯示這個(gè)對(duì)象的類名及內(nèi)存所在地址。如果希望print函數(shù)輸出一個(gè)對(duì)象,能夠顯示對(duì)象的內(nèi)容,就需要在定義類時(shí)重寫__str__()或__repr__()函數(shù)。【例8-18】重寫__str__()函數(shù)。8.7多態(tài)性與運(yùn)算符重載1234567891011121314classItem:def__init__(self,name,price):self.__name=nameself.__price=priceim=Item('鼠標(biāo)',29.8)print(im)classItem:def__init__(self,name,price):self.__name=nameself.__price=pricedef__str__(self):returnself.__name+str(self.__price)im=Item('顯示器',999)print(im)>>><__main__.Itemobjectat0x0000020131024C88>顯示器999代碼第6行用print(im)顯示的是im的類型及所在的內(nèi)存地址。當(dāng)代碼第7行重新定義Item類時(shí),重寫了特殊方法__str__(),第14行再次執(zhí)行print(im)顯示則是成員函數(shù)__str__()函數(shù)的返回值?!纠?-19】定義一個(gè)Point類,有__x,__y兩個(gè)實(shí)例屬性。重載實(shí)現(xiàn)Point對(duì)象與Point對(duì)象(或數(shù)字)之間的+、-,對(duì)象與數(shù)字之間的*、/。8.7多態(tài)性與運(yùn)算符重載1234567891011121314classPoint:def__isNumber(self,n):ifisinstance(n,(int,float)):returnTrueelse:returnFalsedef__init__(self,v1=0,v2=0):self.__x=v1self.__y=v2defsetval(self,v1,v2):self.__x=v1self.__y=v2def__str__(self):returnf'({self.__x},{self.__y})'151617181920212223242526272829303132
def__add__(self,c):t=Point()ifself.__isNumber(c):t.__x=self.__x+ct.__y=self.__y+celse:t.__x=self.__x+c.__xt.__y=self.__y+c.__yreturntdef__sub__(self,c):t=Point()ifself.__isNumber(c):t.__x-=c#t.__x=self.__x-c
t.__y-=c#t.__y=self.__y-celse:t.__x=self.__x-c.__xt.__y=self.__y-c.__yreturnt【例8-19】定義一個(gè)Point類,有__x,__y兩個(gè)實(shí)例屬性。重載實(shí)現(xiàn)Point對(duì)象與Point對(duì)象(或數(shù)字)之間的+、-,對(duì)象與數(shù)字之間的*、/。8.7多態(tài)性與運(yùn)算符重載3334353637383940414243444546
def__mul__(self,t):ifself.__isNumber(t):self.__x*=tself.__y*=treturnselfdef__truediv__(self,t):ifself.__isNumber(t):self.__x/=tself.__y/=treturnselfp1=Point()print(f'p1={p1}')p1.setval(5,-7)print(f'p1={p1}')4748495051525354555657585960p2=Point(10,20)print(f'p2={p2}')p3=p1+p2print(f'p3={p3}')p4=p1-p2print(f'p4={p4}’)p5=p1*2print(f'p1={p1}')print(f'p5={p5}')p6=p2/5print(f'p6={p6}')print(f'p2={p2}')print(f'p1+2={p1+2}')print(f‘p2-3={p2-3}’)#調(diào)用第24行的語(yǔ)句>>>p1=(0,0)p1=(5,-7)p2=(10,20)p3=(15,13)p4=(-5,-27)p1=(10,-14)p5=(10,-14)p6=(2.0,4.0)p2=(2.0,4.0)p1+2=(12,-12)p2-3=(-3,-3)【例8-20】定義復(fù)數(shù)類Comp,有實(shí)部和虛部?jī)蓚€(gè)屬性。通過(guò)函數(shù)重載實(shí)現(xiàn)Comp類對(duì)象之間的+、-、+=、-=運(yùn)算。8.7多態(tài)性與運(yùn)算符重載1234567891011121314classComp:def__isNumber(self,n):ifisinstance(n,(int,float)):returnTrueelse:returnFalsedef__init__(self,v1=0,v2=0):self.__r=v1self.__i=v2defsetval(self,v1,v2):self.__r=v1self.__i=v2def__str__(self):returnf'{self.__r}+{self.__i}i'1516171819202122232425262728293031
def__add__(self,c):if~self.__isNumber(c):t=Comp()t.__r=self.__r+c.__rt.__i=self.__i+c.__ireturntdef__sub__(self,c):if~self.__isNumber(c):t=Comp()t.__r=self.__r-c.__rt.__i=self.__i-c.__ireturntdef__iadd__(self,c):if~self.__isNumber(c):self.__r+=c.__rself.__i+=c.__ireturnself323334353637383940414243444546
def__isub__(self,c):if~self.__isNumber(c):self.__r-=c.__rself.__i-=c.__ireturnselfa=Comp()print(a)a.setval(10,20)print(a)b=Comp(77,88)print(b)c=a+bprint("c=a+b:",c)a+=cprint("a+=c的結(jié)果:",a)>>>0+0i10+20i77+88ic=a+b:87+108ia+=c的結(jié)果:97+128i繼承是用來(lái)實(shí)現(xiàn)代碼復(fù)用和設(shè)計(jì)復(fù)用的機(jī)制,是面向?qū)ο蟪绦蛟O(shè)計(jì)的三大特性之一。繼承機(jī)制允許程序員在保持原有類特性的基礎(chǔ)上,進(jìn)行更具體、更詳細(xì)的說(shuō)明。設(shè)計(jì)一個(gè)新類時(shí),如果可以繼承一個(gè)已有的設(shè)計(jì)良好的類,然后進(jìn)行二次開發(fā),會(huì)大幅度減少開發(fā)工作量。從不同的角度來(lái)看,保持已有類的特性而構(gòu)造新類的過(guò)程稱為繼承。在繼承已有類的特性基礎(chǔ)上,新增自己的特性而產(chǎn)生新類的過(guò)程稱為派生。被繼承的已有類稱為基類或父類,派生出的新類稱為派生類或子類。8.8繼承與派生
8.8繼承與派生派生類主要有3個(gè)部分吸收基類成員。派生類實(shí)際上就包含了它的全部基類中除構(gòu)造函數(shù)之外的所有成員。改造基類成員。如果派生類聲明了一個(gè)和某基類成員同名的新成員,派生的新成員就屏蔽掉外層基類的同名成員。添加新的成員。派生類新成員的加入是繼承與派生機(jī)制的核心,是保證派生類在功能上有所發(fā)展。創(chuàng)建派生類對(duì)象時(shí)調(diào)用派生類的構(gòu)造函數(shù),在構(gòu)造函數(shù)中會(huì)優(yōu)先調(diào)用基類的構(gòu)造函數(shù)來(lái)創(chuàng)建與初始化從基類繼承來(lái)的成員,再創(chuàng)建派生類自己的新成員。8.8繼承與派生類繼承的語(yǔ)法形式如下:在基類Point的基礎(chǔ)上派生出類PointXYZ,即在平面點(diǎn)類的基礎(chǔ)上派生出空間點(diǎn)類。類PointXYZ在繼承類Point的x、y軸坐標(biāo)屬性和一切成員函數(shù)的基礎(chǔ)上,增加z軸坐標(biāo)屬性,以及增加對(duì)z屬性操作的函數(shù),如getZ()函數(shù),來(lái)獲取z屬性的值。于是在定義類PointXYZ時(shí),就不用重復(fù)定義x、y屬性和對(duì)x、y屬性操作的成員函數(shù),很好地實(shí)現(xiàn)了代碼復(fù)用。8.8繼承與派生class類名(基類列表):'''類說(shuō)明'''
類體classPointXYZ(Point):pass定義派生類時(shí),派生類可以繼承基類的公有成員,但不能直接訪問(wèn)基類的私有成員,必須通過(guò)基類公有成員函數(shù)實(shí)現(xiàn)對(duì)基類私有成員的訪問(wèn)。派生類可以直接訪問(wèn)從基類繼承來(lái)的公有成員,就如訪問(wèn)自己的成員一樣,使用“self.成員名”格式來(lái)訪問(wèn)。但如果在派生類中創(chuàng)建了與基類同名的成員函數(shù),派生類會(huì)屏蔽掉同名的外層基類成員函數(shù),這時(shí)候“self.函數(shù)名”只調(diào)用派生類的同名函數(shù)。如果想訪問(wèn)外層基類的同名成員函數(shù),則要通過(guò)“super().基類函數(shù)名(實(shí)參列表)”,或指定基類名的方式“super(派生類名,self).基類函數(shù)名(實(shí)參列表)”、“基類名.基類函數(shù)名(self,實(shí)參列表)”來(lái)實(shí)現(xiàn)。如果基類手動(dòng)定義了構(gòu)造函數(shù),則在派生類的構(gòu)造函數(shù)中一定要顯示調(diào)用基類的構(gòu)造函數(shù)。Python支持多繼承,如果基類中有相同的函數(shù)名,而在子類使用時(shí)沒(méi)有指定是哪個(gè)基類,則Python解釋器將從左向右按順序進(jìn)行搜索。8.8繼承與派生【例8-21】類繼承實(shí)例。8.8繼承與派生123456789101112
1314classPoint:def__init__(self,x=0,y=0):self.__x=xself.y=ydefmove(self,offX,offY):self.__x+=offXself.y+=offYdefgetX(self):returnself.__xclassPointXYZ(Point):def__init__(self,x=0,y=0,z=0):super().__init__(x,y)#或者Point.__init__(self,x,y)self.y=y#本條語(yǔ)句可省self.__z=z1516
1718192021
22232425
defmove(self,offX,offY,offZ):super().move(offX,offY)#或者Point.move(self,offX,offY)self.__z+=offZdefgetZ(self):returnself.__zdef__str__(self):returnf'({self.getX()},{self.y},{self.__z})’p=PointXYZ(2,3,4)p.move(4,-5,-6)print(p.getX(),p.y,p.getZ())print(p)>>>6-2-2(6,-2,-2)【例8-22】類繼承實(shí)例。8.8繼承與派生12345678910111213classA:def__init__(self):self.__private()self.public()def__private(self):print('__private()methodinA')defpublic(self):print('public()methodinA')classB(A):def__private(self):print('__private()methodinB')defpublic(self):print('public()methodinB')14151617181920212223classC(A):def__init__(self):#顯式定義構(gòu)造函數(shù)self.__private()self.public()def__private(self):print('__private()methodinC')defpublic(self):print('public()methodinC')b=B()c=C()>>>__private()methodinApublic()methodinB__private()methodinCpublic()methodinC代碼第22行創(chuàng)建對(duì)象b,會(huì)調(diào)用從類A繼承來(lái)的構(gòu)造函數(shù)__init__,即程序進(jìn)入代碼第3行,由于__init__是類A的函數(shù),調(diào)用的私有函數(shù)成員__private也應(yīng)該是類A的,第4行調(diào)用的public函數(shù)也應(yīng)該是類A的公有成員函數(shù),但由于從類A繼承來(lái)的公有成員函數(shù)public被類B自己創(chuàng)建的公有成員函數(shù)public屏蔽了,就無(wú)法執(zhí)行類A的public函數(shù),只會(huì)調(diào)用類B的public函數(shù)。【例8-23】類繼承實(shí)例。8.8繼承與派生1234567891011121314151617181920classPerson(object):#若某個(gè)類中沒(méi)有指定基類,默認(rèn)基類為object類def__init__(self,ID='',name='',gender='m'):self.setID(ID)self.setName(name)self.setGender(gender)defsetID(self,ID):ifnotisinstance(ID,str):print('IDmustbestring.')returnself.__ID=IDdefsetName(self,name):ifnotisinstance(name,str):print('name
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 貴陽(yáng)職業(yè)技術(shù)學(xué)院《區(qū)域分析與區(qū)域規(guī)劃》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025年云南建筑安全員B證(項(xiàng)目經(jīng)理)考試題庫(kù)
- 貴陽(yáng)人文科技學(xué)院《測(cè)量平差》2023-2024學(xué)年第一學(xué)期期末試卷
- 廣州中醫(yī)藥大學(xué)《通信經(jīng)濟(jì)學(xué)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025云南省安全員C證考試(專職安全員)題庫(kù)附答案
- 2025年海南省安全員知識(shí)題庫(kù)及答案
- 廣州應(yīng)用科技學(xué)院《大數(shù)據(jù)案例分析》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025安徽省安全員-B證考試題庫(kù)附答案
- 2025上海市安全員《C證》考試題庫(kù)
- 《組合圖形面積》課件
- 高級(jí)FAE現(xiàn)場(chǎng)應(yīng)用工程師工作計(jì)劃工作總結(jié)述職報(bào)告
- 河道整治工程監(jiān)理的實(shí)施細(xì)則
- 管轄權(quán)異議仲裁申請(qǐng)書
- 2022神經(jīng)外科手術(shù)分級(jí)目錄
- 電氣傳動(dòng)自動(dòng)控制系統(tǒng)課程設(shè)計(jì)報(bào)告書
- (完整版)中考英語(yǔ)作文必備好詞好句
- T-CERDS 3-2022 企業(yè)ESG評(píng)價(jià)體系
- 報(bào)價(jià)經(jīng)理崗位職責(zé)
- 汝州某燃煤熱電廠施工組織設(shè)計(jì)
- 豬場(chǎng)配懷工作安排方案設(shè)計(jì)
- 《廣東省普通高中學(xué)生檔案》模板
評(píng)論
0/150
提交評(píng)論