




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
面向對象編程(ObjectOrientedProgramming,OOP)是一種程序設計架構,同時也是一種程序開發的方法。第5章面向對象編程目錄第5章面向對象編程5.1類和對象5.1.1類和對象的概念5.1.2類的定義5.1.3類的成員5.1.4創建對象5.1.5在類的內部調用實例方法5.1.6構造方法5.1.7類變量、實例變量及其作用域5.1.8實例方法、類方法和靜態方法5.2類的封裝5.2.1封裝的概念5.2.2用私有變量、私有方法實現封裝5.2.3用@property裝飾器定義屬性實現封裝
5.3類的繼承5.3.1繼承的概念5.3.2使用繼承5.3.3重寫方法5.3.4派生屬性或方法5.3.5多重繼承5.4類的多態5.4.1多態的實現5.4.2多態性5.5習題5.1類和對象5.1.1類和對象的概念對象(Object)抽象為類(Class)的過程,是在系統分析階段完成的。在現實世界中,先有一個一個具體的對象,然后將對象進行分類,總結出類。在程序中,必須先定義類,后調用類來產生對象。類并不能直接使用,通過類創建出的實例(又稱對象)才能使用。5.1類和對象5.1.2類的定義在編程時,使用類的順序是:先定義(創建)類,然后再創建類的對象(實例),通過對象實現特定的功能。Python中,創建一個類使用class關鍵字實現,其基本語法格式如下:class類名:
類的成員1…
類的成員n5.1.3類的成員在類的定義中,類的成員可以分為3種:類變量、方法和屬性。屬性在“5.2類的封裝”介紹,這里先介紹類變量和方法。1.類變量Python中,類中的變量分為:類變量和實例變量。這里介紹類變量。在類體中定義的變量稱為類變量(也稱類字段、成員字段、成員變量),類變量也是廣義上的屬性,稱為類屬性。格式如下。class類名:
類變量名=初值
…
類的其他成員說明:1)類變量是指在類中,且在方法之外定義的變量。2)初值表示該字段的初始狀態,例如:student_age=18#年齡,整型,初值18歲5.1類和對象2.實例方法在類的內部,使用def關鍵字定義實例方法,語法格式如下。class類名:
類變量名=值
…def方法名(self,形參1,形參2,…,形參n)self.實例變量名=值變量名=值方法體
return表達式類的其他成員實例方法必須包含參數self,且為第一個參數,不能省略。5.1類和對象5.1類和對象【例5-1】定義學生類Student。屬性:姓名name、性別gender、年齡age、班級grade。方法:顯示學習的課程learn(course),course是顯示的課程名稱;顯示考試的課程exam(course,score),course是課程,score是成績。classStudent:#定義類
#定義類變量
name=""#姓名
gender="男"#性別,默認“男”
age=18#年齡,默認18歲
grade=""#班級
#定義實例方法
definfo(self):print(,self.gender,self.age,self.grade)#在方法中訪問類變量使用self關鍵字
deflearn(this,course):#獲取學習課程字符串的方法,形參course代表課程
+"正在學習"+course#self可以換成任何標識符,這里是thisdefexam(self,course,score):#獲取考試課程字符串的方法,形參course代表課程,score代表成績
string=+course+"的考試成績是"+str(score)#定義局部變量stringreturnstring5.1類和對象【例5-2】計算長方體的體積和表面積。定義長方體類Cuboid。屬性:長length、寬width、高height。方法:計算長方體的體積cubage,長方體的體積=長×寬×高;計算長方體的表面積totalArea,長方體的表面積=(長×寬+長×高+寬×高)×2。classCuboid:#定義類變量
length=0#長
width=0#寬
height=0#高
#定義實例方法
defcubage(self):#計算長方體的體積
returnself.length*self.width*self.heightdeftotal_area(self):#計算長方體的表面積
return(self.length*self.width+self.length*self.height+self.width*self.height)*25.1類和對象【例5-2】計算長方體的體積和表面積。定義長方體類Cuboid。屬性:長length、寬width、高height。方法:計算長方體的體積cubage,長方體的體積=長×寬×高;計算長方體的表面積totalArea,長方體的表面積=(長×寬+長×高+寬×高)×2。也可以把方法改成傳參的形式,代碼如下:classCuboid1:#定義實例方法
defcubage(self,length,width,height):#計算長方體的體積,形參:長,寬,高
returnlength*width*heightdeftotal_area(self,length,width,height):#計算長方體的表面積,形參:長,寬,高
return(length*width+length*height+width*height)*25.1.4創建對象1.創建對象創建類的實例也稱實例化一個類的對象,簡稱創建對象。對已創建的類進行實例化,其語法格式如下:類名()創建的對象或實例賦值給一個變量,賦值后該變量就表示這個類的一個對象。其格式為:變量名(或稱對象名)=類名()例如,下面的代碼創建Student類的實例,并賦給stu對象,對stu對象進行初始化。stu=Student()#創建Student類的實例,并賦值給stu變量,stu變量的類型是類Student的類型5.1類和對象2.對象訪問實例變量和實例方法(1)對象訪問實例變量在主程序中(或類的外部),使用已創建的對象訪問類中變量(實例變量或類變量)的語法格式如下:對象名.變量名注意:實例變量只能通過“對象名.實例變量名”訪問,無法通過“類名.實例變量名”訪問。為對象中的變量(實例變量或類變量)賦值的語法格式如下:對象名.變量名=值(2)對象訪問實例方法訪問對象中實例方法的語法格式如下:對象名.方法名(實參1,實參2,…,實參n)注意:對象名與實例變量名、方法名之間用點“.”連接。5.1類和對象3.類和對象應用示例【例5-3】通過在例5-1中已經定義的類,創建兩個對象,分別是“劉強”和“王芳”。liuqiang=Student()#創建Student()類的一個對象,并賦值給liuqiang變量#初始化類變量="劉強"#用“對象名.類變量”訪問liuqiang.age=19liuqiang.grade="計算機科學2019"#調用方法()#顯示liuqiang對象的基本信息print(liuqiang.learn("數學"))print(liuqiang.exam("數學",85))print()#顯示一個空行,用于隔開兩位學生的信息wangfang=Student()#創建Student()類的一個對象,并賦值給wangfang變量#初始化類變量="王芳"wangfang.gender="女"wangfang.age=18wangfang.grade="哲學2019"5.1類和對象5.1類和對象#調用方法()print(wangfang.learn("英語"))print(wangfang.exam("英語",96))【例5-4】在例5-2定義類的基礎上,編寫創建對象和調用屬性、方法的代碼。cu=Cuboid()#Cuboid()類的一個對象,并賦值給cu變量cu.length=10#長cu.width=20#寬cu.height=30#高print(cu.cubage())print(cu.total_area())調用Cuboid1()中帶參數的方法,代碼如下:cu1=Cuboid1()#Cuboid1()類的一個對象,并賦值給cu1變量print(cu1.cubage(10,20,30))print(cu1.total_area(10,20,30))5.1類和對象5.1.5在類的內部調用實例方法在類的內部調用實例方法的格式為:self.方法名(實參1,實參2,…,實參n)或類名.方法名(self,實參1,實參2,…,實參n)在類的內部調用實例方法,如果不使用類名調用方法,則方法名前使用self;如果使用類名調用方法,則實參列表中使用self。【例5-5】在類的內部和外部調用實例方法示例。classHuman:defeat(self,name):=name#把形參name賦值給創建的實例變量print("eatand%s"%)defdrink(self):self.eat("drink")#在類中訪問方法:self.方法名()Human.eat(self,"drink")#在類中調用方法:類名.方法名(self)man=Human()#創建對象man.drink()#在類外調用方法,對象調用方法:對象名.方法名()5.1類和對象5.1.6構造方法1.構造方法的概念當創建一個對象時,對象表示一個實體。例如,下面的代碼st=Student()#創建對象="張三"#設置屬性值,使該對象的name值為"張三"st.age=18#設置屬性值,使該對象的age值為18構造方法又叫構造函數、構造器,它是類的一種特殊的成員方法,在創建類的新對象時自動調用構造方法。它主要用于在創建對象時初始化對象,即為對象成員變量賦初始值。2.定義構造方法在創建類時,可以添加一個__init__()方法。該方法是一個特殊的類實例方法,稱為構造方法。每個類都必須至少有一個構造方法。構造方法的語法格式如下:def__init__(self,形參1,形參2,…,形參n):self.實例變量名1=值1self.實例變量名2=值2
方法體構造方法是類的一個特殊的成員方法,除了具有一般成員方法的特點外,它還有自己獨有的特點。5.1類和對象5.1類和對象3.調用構造方法在聲明類時,一個類中會包默認的構造方法,也可能包含自定義構造方法。(1)調用默認構造方法假設一個類包含默認的構造方法,則調用默認構造方法的語法如下。對象名=類名()(2)調用自定義構造方法自定義構造方法包括無參或有參構造函數。1)調用自定義無參構造方法。自定義無參構造方法的調用與默認構造方法的調用相同。2)調用有參構造方法。調用有參構造方法的語法如下。對象名=類名(實參1,實參2,…,實參n)實參列表中的參數可以是數據對象、變量或表達式,參數之間用逗號分隔。例如,如下代碼在創建Student對象時傳入參數:st=Student("張三豐",18)print(,st.age)5.1類和對象4.構造方法實例【例5-6】在Student類的__init__()方法中,定義兩個實例變量gender和age,并且直接賦值。在創建Student的對象st時,采用無參數創建對象,它會隱式調用__init__()方法,然后Student類的對象st中的實例變量就被賦值了。classStudent:def__init__(self):#定義無參構造方法
print("調用構造方法")self.gender="男"#self.gender表示gender是實例變量,通過“=”創建該實例變量
self.age=18st=Student()#創建對象,構造方法無參數print("st的性別:{0},年齡:{1}".format(st.gender,st.age))5.1類和對象【例5-7】用__init__()方法傳遞參數。classStudent:def__init__(self,name,gender,age):#定義有參構造方法,小括號中是定義的形參名
print("調用構造方法")=name#“=”左邊的name是定義的實例變量,右邊的name是形參名
self.gender=genderself.age=agest=Student("王芳","女",19)#有參數創建對象print("st的姓名:{0},性別:{1},年齡:{2}".format(,st.gender,st.age))5.1類和對象【例5-8】對例5-2中的類,用__init__()方法重新定義類。classCuboid:def__init__(self,length,width,height):self.length=length#實例變量作為屬性用
self.width=widthself.height=heightdefcubage(self):#計算長方體的體積
returnself.length*self.width*self.height#訪問實例變量
deftotal_area(self):#計算長方體的表面積
return(self.length*self.width+self.length*self.height+self.width*self.height)*2if__name__=='__main__':cu=Cuboid(10,20,30)#創建對象,用構造方法的參數初始化
print(cu.cubage())print(cu.total_area())5.1類和對象【例5-9】定義一個兩個數的加法類NumberAdd,通過__init__()方法初始化兩個數,定義一個實例方法add()計算兩個數的和。classNumberAdd:a=5#定義在類中但在函數體外的變量為類變量
def__init__(self,a,b):self.x=a#self.x、self.y是實例變量
self.y=b#a、b是形參,a、b是本方法內的局部變量
print("a={0},b={1}".format(a,b))print("self.x={0},self.y={1}".format(self.x,self.y))print("self.a=",self.a)defadd(self):#定義兩個數相加的方法
sum=self.x+self.y#在類內訪問實例變量
returnsumprint("a=",a)#顯示類變量a的值if__name__=='__main__':a=10#加數
b=20#被加數
number=NumberAdd(a,b)#創建對象并初始化
print("{0}+{1}={2}".format(a,b,number.add()))#顯示兩個數的和運行結果如下:a=5a=10,b=20self.x=10,self.y=20self.a=510+20=305.1類和對象5.1.7類變量、實例變量及其作用域1.類變量類變量是指在類中且在方法之外定義的變量。在主程序中(或類的外部),類變量推薦用“類名.類變量名”訪問,但也可以使用“對象名.類變量名”訪問(此方式不推薦使用,即類變量通常不作為實例變量使用)。【例5-10】訪問例5-1中定義的類變量name、gender、age和grade。S="劉強"#用“類名.類變量”訪問Student.gender="男"Student.age=19Student.grade="計算機科學2019"5.1類和對象2.實例變量從實例化的角度來說,實例變量的定義為,實例化之后,每個實例(對象)單獨擁有的變量叫作實例變量。實例變量是與某個類的實例相關聯的數據值,這些值獨立于其他實例或類。注意,實例變量只能通過對象名訪問,無法通過類名直接訪問。在方法中,只要以self定義的變量都是實例變量。實例變量的定義如下:self.變量名=值調用實例變量有如下兩種方式。1)在類外通過對象直接調用。2)在類內通過self間接調用。5.1類和對象【例5-11】類變量和實例變量在訪問和賦值后的不同。classDemo:aa="我是類變量aa"deffunc(self,name):self.bb=name#bb是實例變量if__name__=='__main__':print("Demo.aa=",Demo.aa)Demo.aa="Demo類,為類變量aa第1次賦值"obj1=Demo()#創建對象obj1#obj1.aa="obj1對象,為實例變量aa賦值"#稍后取消注釋
obj1.func("obj1對象,為實例變量bb賦值")print("Demo.aa=",Demo.aa)#顯示類變量Demo.aa的值
print("obj1.aa=",obj1.aa)#顯示對象obj1.aa的值
print("obj1.bb=",obj1.bb)#顯示對象obj1.bb的值
print()obj2=Demo()#創建對象obj25.1類和對象#obj2.aa="obj2對象,為實例變量aa賦值"#稍后取消注釋
obj2.func("obj2對象,為實例變量bb賦值")Demo.aa="Demo類,為類變量aa第2次賦值"print("Demo.aa=",Demo.aa)#訪問Demo.aaprint("obj2.aa=",obj2.aa)#訪問obj2.aaprint("obj2.bb=",obj2.bb)#訪問obj2.bbprint()print("id(Demo.aa)=",id(Demo.aa))#顯示內存中的地址
print("id(obj1.aa)=",id(obj1.aa))print("id(obj2.aa)=",id(obj2.aa))5.1類和對象3.實例變量的作用域私有成員在類的外部不能直接訪問,如果要在類的外部訪問,只能通過調用類里面的公有成員方法間接訪問,或者通過Python支持的特殊方式訪問。【例5-12】在__init__()方法中初始化一個實例變量及一個私有的實例變量。定義一個給實例變量賦值的方法、一個給私有變量賦值的方法、一個得到實例變量的方法,以及一個得到私有變量的方法。5.1類和對象classTest:def__init__(self,x,y):self._x=x#定義實例變量
self.__y=y#定義私有的實例變量
defsetX(self,x):self._x=x#給實例變量賦值
defsetY(self,y):self.__y=y#給私有的實例變量賦值
defgetX(self):returnself._x#得到實例變量
defgetY(self):returnself.__y#得到私有的實例變量
defshow(self):print('self._x=',self._x)#在類內訪問實例變量
print('self.__y=',self.__y)#在類內訪問私有的實例變量if__name__=='__main__':t=Test(2,3)#創建對象并初始化
print('創建對象并初始化后顯示_x,__y(2,3)的值')print(t._x)#在類外訪問實例變量
print(t.__y)#在類外訪問對象的私有變量5.1類和對象把類外的程序改為如下。if__name__=='__main__':t=Test(2,3)#創建對象并初始化
print('創建對象并初始化后顯示_x,__y(2,3)的值')t.show()#調用實例方法t.show()print(t.getX(),t.getY())#調用實例方法t.getX(),t.getY()t._x=4#給實例變量賦值
t.__y=5#這里實際是新建了一個與私有變量__y同名的變量
print('給變量賦值后顯示_x,__y(4,5)的值(__y的值沒有變)')t.show()#self.__y的顯示結果仍是3print(t.getX(),t.getY())t.setX(6)t.setY(7)#用方法給私有變量賦值,賦值成功
print('用方法設置值后顯示_x,__y(6,7)的值')t.show()print(t.getX(),t.getY())print(t._Test__y)#用特殊方法訪問私有變量5.1類和對象運行顯示結果如下:創建對象并初始化后顯示_x,__y(2,3)的值self._x=2self.__y=323給變量賦值后顯示_x,__y(4,5)的值(__y的值沒有變)self._x=4self.__y=343用方法設置值后顯示_x,__y(6,7)的值self._x=6self.__y=76775.1類和對象在Python中,以下畫線開頭的變量名和方法名有特殊的含義,尤其是在類的定義中,用下畫線作為變量名和方法名前綴和后綴來表示類的特殊成員。1)_×××:這樣的變量名或方法名叫保護成員,不能用“frommoduleimport*”導入,只有類對象和子類對象能訪問。2)__×××__:系統定義的特殊成員。3)__×××:類中的私有成員,只有類對象自己能訪問,子類對象也不能訪問這個成員,但在對象外部可以通過“對象名._類名__×××”這樣的特殊方式來訪問。也就是說,Python中不存在嚴格意義上的私有成員。在IDLE的文件方式或交互方式中,在對象或類名后輸入一個小數點“.”后等3秒鐘,則會顯示一個列表框,列出其所有公開成員,如圖5-5所示,模塊也具有同樣的特點。如果在小數點“.”后面再加一個下畫線,則會在列表框中列出該對象或類的所有成員,包括私有成員,如圖5-6所示。5.1類和對象5.1.8實例方法、類方法和靜態方法1.實例方法在定義方法時,如果方法的形參以self作為第一個參數,則該方法為實例方法(也稱普通方法)。構造方法也屬于實例方法,只不過它比較特殊。在類內,分別使用“self.類變量名”和“self.實例變量名”訪問類變量和實例變量。2.類方法在定義方法時,如果方法的形參以cls作為第一個參數,并且使用@classmethod修飾,則該方法為類方法。注意,如果沒有@classmethod修飾,則Python解釋器會將該方法認定為實例方法,而不是類方法。在類方法內,使用“cls.類變量名”訪問類變量,但是不能訪問實例變量。3.靜態方法在定義方法時,如果不設置默認參數,并且使用@staticmethod修飾,則該方法為靜態方法。靜態方法其實就是函數,它與函數的區別是,靜態方法定義在類這個空間(類命名空間)中,而函數則定義在程序所在的空間(全局命名空間)中。靜態方法沒有self、cls等特殊參數。靜態方法可以通過類名或實例對象名來調用。5.1類和對象【例5-13】在Person類中定義實例方法、類方法、靜態方法,然后用類名、對象名訪問這些方法。classPerson:gender="Male"#定義類變量(靜態的變量)
def__init__(self,name="Jack",age=18):#構造方法也屬于實例方法
=name#定義實例變量
self.age=agedefshow(self):#定義實例方法
return'實例方法show:'++self.gender+str(self.age)#類內訪問實例變量、類變量
@classmethod#classmethod修飾的方法是類方法
defeat(cls,name,age):eat_name=name#類方法內無法訪問實例變量
eat_gender=cls.gender#使用“cls.類變量名”訪問類變量
eat_age=str(age)#方法內定義的變量,類外不可用
return'類方法eat:'+eat_name+eat_gender+eat_age@classmethod#classmethod修飾的方法是類方法
defrun(cls):return'類方法run:'+str(cls)
@staticmethod#staticmethod修飾的方法是靜態方法
defsleep(a):#s=self.x+#靜態方法內無法訪問類變量和實例變量
s="zZ@#"+a#方法內定義的變量,類外不可用
return'靜態方法sleep:'+sprint("用類名調用",Person.eat("Jack",18))#用類名調用方法,Person類會自動綁定到第一個參數print("用類名調用",Person.run())#用類名調用類方法,Person類會自動綁定到第一個參數print("用類名調用",Person.sleep("ZZZ..."))#用類名調用靜態方法per=Person("Jenny",19)#創建對象print("用對象名調用",per.eat("Jenny",19))#用對象調用eat()類方法,其實依然是使用類調用print("用對象名調用",per.run())#因此第一個參數依然被自動綁定到Person類print("用對象名調用",per.sleep("zzz..."))#用對象調用靜態方法print("用對象名調用",per.show())#用對象調用show()實例方法運行結果為:用類名調用類方法eat:JackMale18用類名調用類方法run:<class'__main__.Person'>用類名調用靜態方法sleep:zZ@#ZZZ...用對象名調用類方法eat:JennyMale19用對象名調用類方法run:<class'__main__.Person'>用對象名調用靜態方法sleep:zZ@#zzz...用對象名調用實例方法show:JennyMale195.1類和對象5.2.1封裝的概念封裝實際上有兩個方面的含義:把該隱藏的隱藏起來,把該暴露的暴露出來。由于Python并沒有提供類似于其他程序語言的private等的修飾符,因此Python并不能真正支持隱藏。Python中的封裝有兩種方法:1)用私有變量、私有方法實現封裝。2)用@property裝飾器定義屬性實現封裝。5.2.2用私有變量、私有方法實現封裝Python不能真正支持隱藏。為了隱藏類中的成員,Python行業建議將類的成員命名為以雙下畫線開頭,這樣程序員在看到雙下劃線開頭的屬性時,就知道是隱藏屬性,也就不在外部訪問了。5.2類的封裝【例5-14】定義長方形類Rectangle,在構造方法中設置私有實例變量寬__width和高__height。分別對寬、高定義get方法、set方法、del方法。再定義一個計算面積的方法area()。classRectangle:#定義長方形類
def__init__(self,width=0,height=0):#定義構造方法
self.__width=width#創建實例變量,寬
self.__height=height#創建實例變量,高
defgetwidth(self):#定義getwidth()方法,返回寬
returnself.__widthdefsetwidth(self,width):#定義setwidth()方法,設置寬
self.__width=widthdefdelwidth(self):#定義delwidth()方法
self.__width=0defgetheight(self):#定義getheight()方法,返回高
returnself.__heightdefsetheight(self,height):#定義setheight()方法,設置高
self.__height=heightdefdelheight(self):#定義delheight()方法
self.__height=0
5.2類的封裝5.2類的封裝defarea(self):#定義計算面積的方法area()returnself.__width*self.__height#按設置的寬、高計算面積rect=Rectangle()#創建對象,用默認值初始化實例rect.setwidth(20)#設置寬rect.setheight(30)#設置高print(rect.getwidth())#得到寬print(rect.getheight())#得到高print(rect.area())#計算面積運行結果如下:20306005.2類的封裝5.2.3用@property裝飾器定義屬性實現封裝1.用@property裝飾器定義屬性(推薦)定義方法時,使用@property裝飾器可以把一個實例方法變成其同名屬性,以支持“對象名.屬性名”的訪問。用@property定義屬性的語法格式如下:@property#定義只讀屬性def屬性名(self)
代碼塊1@屬性名.setter#定義可修改屬性def屬性名(self,value):
代碼塊2@屬性名.deleter#定義刪除屬性def屬性名(self):
代碼塊3【例5-15】把例5-14改成用@property裝飾器定義屬性。classRectangle:#定義長方形類
def__init__(self,width=0,height=0):#定義構造方法
self.__width=width#創建實例變量,寬
self.__height=height#創建實例變量,高
@propertydefwidth(self):#定義只讀屬性width,返回寬
returnself.__width@width.setterdefwidth(self,width):#定義設置屬性width,設置寬
self.__width=width@width.deleterdefwidth(self):#定義刪除屬性widthself.__width=0@propertydefheight(self):#定義只讀屬性height,返回高
returnself.__height5.2類的封裝@height.setterdefheight(self,height):#定義設置屬性height,設置高
self.__height=height@height.deleterdefheight(self):#定義刪除屬性heightself.__height=0defarea(self):#定義計算面積的方法area()returnself.__width*self.__height#按設置的寬、高計算面積rect=Rectangle()#創建對象,用默認值初始化實例rect.width=20#用屬性設置寬rect.height=30#用屬性設置高print("rect.width=",rect.width)#得到寬print("rect.height=",rect.height)#得到高print("rect.area()=",rect.area())#計算面積print(rect._Rectangle__width)#訪問私有變量運行程序的結果如下:rect.width=20rect.height=30rect.area()=600205.2類的封裝5.2類的封裝【例5-16】對設定的屬性值進行數據校驗,并給出相應的提示。classStudent(object):def__init__(self,name,age):self._name=nameself._age=ageself._weight=45@propertydefname(self):returnself._name@name.setterdefname(self,value):iftype(value)==str:self._name=valueelse:self._name='Noname.'@propertydefage(self):returnself._age5.2類的封裝@age.setterdefage(self,value):ifvalue>0andvalue<100:self._age=valueelse:self._age='invalidagevalue.'@propertydefweight(self):returnself._weight@weight.setterdefweight(self,value):self._weight=value;t=Student('Tom',19)print('Name:',)print('Age:',t.age)print('weight:',t.weight)print('-'*50)='Jack't.age=300t.weight=50print('Name:',)print('Age:',t.age)print('weight:',t.weight)運行結果如下:Name:TomAge:19weight:45--------------------------------------------------Name:JackAge:invalidagevalue.weight:505.2類的封裝2.用property()函數定義屬性用property()函數定義屬性的語法格式如下:屬性名=property(get方法名,set方法名,del方法名,'描述信息')【例5-17】如下程序中,使用property()函數定義一個width屬性,在定義該屬性時傳入4個參數,設置該屬性可讀、可寫、可刪除,也有說明文檔。classRectangle:#定義長方形類
def__init__(self,width=0,height=0):#定義構造方法
self._width=width#創建實例變量,寬
self._height=height#創建實例變量,高
defgetwidth(self):#定義getwidth()方法,返回寬
returnself._widthdefsetwidth(self,width):#定義setwidth()方法,設置寬
self._width=widthdefdelwidth(self):#定義delwidth()方法
self._width=0width=property(getwidth,setwidth,delwidth,'矩形的寬屬性')#使用property定義width屬性5.2類的封裝defgetheight(self):#定義getsize()方法,返回高
returnself._heightdefsetheight(self,height):#定義setheight()方法,設置高
self._height=heightdefdelheight(self):#定義delheight()方法
self._height=0height=property(getheight,setheight,delheight,'矩形的高屬性')#使用property定義height屬性
defarea(self):#定義計算面積的方法area()returnself._width*self._height#按設置的寬、高計算面積print("訪問width屬性的說明文檔:",Rectangle.width.__doc__)#訪問width屬性的說明文檔print("通過內置的help()函數查看Rectangle.width的說明文檔:")help(Rectangle.width)#通過內置的help()函數查看Rectangle.width的說明文檔rect=Rectangle(10,20)#創建對象,并初始化實例print('rect.width=',rect.width)#訪問rect的width屬性rect.width=30#對rect的width屬性賦值print('rect._width=',rect._width)#訪問rect的_width實例變量print('rect._height=',rect._height)#訪問rect的_height實例變量print('rect.area()=',rect.area())#計算面積5.2類的封裝delrect.width#刪除rect的width屬性print('rect._width=',rect._width)#訪問rect的_width實例變量print('rect._height=',rect._height)#訪問rect的_height實例變量print('rect.area()=',rect.area())#計算面積運行結果如下:訪問width屬性的說明文檔:矩形的寬屬性通過內置的help()函數查看Rectangle.width的說明文檔:Helponproperty:
矩形的寬屬性rect.width=10rect._width=30rect._height=20rect.area()=600rect._width=0rect._height=20rect.area()=05.2類的封裝【例5-18】用屬性方法實現例5-16。classStudent:def__init__(self,name,age):self._name=nameself._age=ageself._weight=45defget_name(self):returnself._namedefset_name(self,value):iftype(value)==str:self._name=valueelse:self._name='Noname'name=property(fget=get_name,fset=set_name,fdel=None,doc='nameofanstudent')defget_age(self):returnself._age5.2類的封裝defset_age(self,value):ifvalue>0andvalue<100:self._age=valueelse:self._age='invalidagevalue.'age=property(fget=get_age,fset=set_age,fdel=None,doc='ageofanstudent')defget_weight(self):returnself._weightdefset_weight(self,value):self._weight=valueweight=property(fget=get_weight,fset=set_weight,fdel=None,doc='weightofanstudent')t=Student('Tom',19)print('Name:',)print('Age:',t.age)print('weight:',t.weight)print('-'*50)='Jack't.age=300t.weight=505.2類的封裝print('Name:',)print('Age:',t.age)print('weight:',t.weight)print(S.__doc__)運行結果如下:Name:TomAge:19weight:45--------------------------------------------------Name:JackAge:invalidagevalue.weight:50nameofanstudent5.3類的繼承5.3.1繼承的概念所謂繼承就是使用已存在的類的定義作為基礎建立新類的技術。已存在的類稱為基類、父類或超類(BaseClass、FatherClass、SuperClass)。新建的類稱為派生類(DerivedClass)或子類(SubClass)。通過繼承,一個新建子類從已有的父類那里獲得父類的特性和行為。5.3.2使用繼承子類繼承父類的語法格式如下:class子類名(父類名1,父類名2,…):[類變量=值][def__init__(self,參數表):
方法體1][def方法名(self,參數表):
方法體2]
類的成員1
類的成員2…5.3類的繼承【例5-19】子類調用父類的公有變量和方法示例。classFather:#定義父類
car=3#定義類變量,公有的屬性
defdrive(self):#定義方法,公有的方法
print('Fathercandriveacar!')classSon(Father):#子類繼承父類
pass#空語句tom=Father()#父類創建對象print(tom.car)#父類對象調用自己的類變量tom.drive()#父類對象調用自己的方法print('-'*50)#顯示50個“-”jerry=Son()#子類創建對象print(jerry.car)#子類調用父類的類變量jerry.drive()#子類調用父類的方法運行結果如下:3Fathercandriveacar!--------------------------------------------------3Fathercandriveacar!5.3類的繼承5.3.3重寫方法如果父類的某些方法不能滿足子類的需求,可以在子類中對父類的方法進行選擇性的修改,包括形參、方法體、返回值等,甚至覆蓋(全部修改),稱為重寫方法或方法的重寫。1.構造方法的重寫若要在子類中調用父類的構造方法,就要在子類的構造方法中顯式調用父類的構造方法,有兩種方式。1)Python3以前版本的調用語法為:ParentClassName.__init__(self,parameters)2)Python3的調用語法為:super().__init__(parameters)建議使用Python3的調用語法,因為它可以解決類名變動后引起的修改問題。5.3類的繼承【例5-20】在子類的構造方法中調用父類構造方法示例。classFather(object):def__init__(self,name,age):=name#父類的實例變量不能定義為私有(如__name),否則不能繼承
self.age=agedefdrive(self):#定義方法,公有的方法
print('Fathercandriveacar!')classSon(Father):def__init__(self,name,age,weight):#先繼承,再重構
#Father.__init__(self,name,age)#經典類繼承父類的構造方法
super().__init__(name,age)#新式類繼承父類的構造方法
self.weight=weight#定義類的本身屬性
defwalk(self):print('Soniswalking...')defdisplay(self):print(,self.age,self.weight)#、self.age繼承父類jerry=Son('Jerry',19,50)#創建對象并初始化print(,jerry.age,jerry.weight)#顯示屬性值jerry.drive()#子類對象調用父類方法jerry.walk()#子類對象調用自己的方法jerry.display()運行結果如下:Jerry1950Fathercandriveacar!Soniswalking...Jerry19505.3類的繼承2.方法的重寫在子類中調用父類的實例方法有3種方式。1)用父類名調用,要傳遞self參數;調用本類的實例成員時不需要加self參數。語法格式為:父類名.父類的方法名(self,參數列表)2)用當前類名調用,語法格式為:super(當前類名,self).父類的方法名(參數列表)3)最新語法,不用寫類名。建議使用本方法。語法格式為:super().父類的方法名(參數列表)5.3類的繼承【例5-21】子類重寫父類的方法示例。classFather:#定義父類
defdrive(self):#定義方法,公有的方法
print('Fathercandriveacar!')classSon(Father):#子類繼承父類
defdrive(self):#重寫父類的方法drive(),方法的參數列表與父類的可以不相同
print('Soncandriveasportscar!')#跑車
super().drive()#在子類中直接調用父類的方法drive()tom=Father()#父類創建對象tom.drive()#父類對象調用自己的方法jerry=Son()#子類創建對象jerry.drive()#子類調用自己的方法程序運行結果如下:Fathercandriveacar!Soncandriveasportscar!Fathercandriveacar!5.3類的繼承5.3.4派生屬性或方法在父類中沒有的屬性或方法,如果在子類中定義了,這樣的屬性或方法就叫作派生屬性或派生方法。派生屬性或方法其實就是在子類中增加自己的屬性或方法。【例5-23】并在子類中派生屬性和方法。classPerson(object):#定義父類
def__init__(self,name,gender,age):=nameself.gender=genderself.age=ageclassStudent(Person):#Student繼承Personid='1000'#在子類中增加類變量
defget_id(self):#在子類中增加實例方法
returnself.iddefshow(self,credit):#在子類中增加實例方法
self.credit=sum(credit)#計算學分列表的和
id=self.get_id()#在類的內部調用實例方法
str='Studentname:{},gender:{},age:{},credit:{},id:{}'.format(,self.gender,self.age,self.credit,id)returnstr5.3類的繼承if__name__=='__main__':jenny=Student("Jack",19,"boy")#子類Student創建對象,執行子類自己的構造方法
credits=[5,10,20,8,10,8,20,15,30,10,20,30]print(jenny.show(credits))運行結果如下:Studentname:Jack,gender:19,age:boy,credit:186,id:10005.3類的繼承【例5-24】用繼承關系定義校園中的人員類,包括教師、學生。分析:由于教師、學生等人員有許多共同的屬性和方法,所以可以把共同的屬性和方法定義為父類(人員類Person),然后派生出教師類Teacher、學生類Student。如下程序。classPerson:#定義父類
def__init__(self,name,age,addr,hoppy):=name#姓名
self.age=age#年齡
self.addr=addr#地址
self.hoppy=hoppy#愛好
deftell(self):print('姓名:%s,年齡:%s,地址:%s,愛好:%s'%(,self.age,self.addr,self.hoppy))classTeacher(Person):#定義子類
def__init__(self,name,age,addr,hoppy,salary):super().__init__(name,age,addr,hoppy)#在子類的構造方法中調用父類的構造方法
self.salary=salary#月薪
deftell(self):#重寫方法
Person.tell(self)#在子類中直接調用父類的方法tell()print('我的月薪是:%s'%self.salary)5.3類的繼承classStudent(Person):#定義子類
def__init__(self,name,age,addr,hoppy,marks):Person.__init__(self,name,age,addr,hoppy)#在子類的構造方法中調用父類的構造方法
self.marks=marks#成績
deftell(self):#重寫方法
super().tell()#在子類中直接調用父類的方法tell()print('我的成績是:%d'%self.marks)t=Teacher('王剛','45','北京','旅游',8000)#創建教師對象,并初始化對象t.tell()#調用教師對象的方法s=Student('李芳',18,'上海','美食',95)s.tell()程序運行結果為:姓名:王剛,年齡:45,地址:北京,愛好:旅游我的月薪是:8000姓名:李芳,年齡:18,地址:上海,愛好:美食我的成績是:955.3類的繼承【例5-25】例5-24用屬性實現。classPerson:#定義父類
def__init__(self,name,age):self.__name=name#姓名
self.__age=age#年齡
@propertydefname(self):#定義只讀屬性namereturnself.__name#類內訪問實例變量
@name.setterdefname(self,name):#定義設置屬性nameself.__name=nam
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025辦公室租賃合同示范文本
- 第二單元第2課《溫馨一角》教學設計-2024-2025學年桂美版(2024)初中美術七年級下冊
- 優化教育生態實施方案推動可持續發展
- 全面推進公共領域電動化試點計劃
- 美育浸潤行動推進方案
- 死亡賠償協議書
- 接待當事人心得體會
- 制定多渠道營銷的工作方案計劃
- 教育行業品牌推廣方案計劃
- 2025年國際金融理財師考試的網絡學習模式試題及答案
- 閱讀提取信息課件
- 2025年河南省中考數學二輪復習壓軸題:動態幾何問題專練
- 江蘇省2024年中職職教高考文化統考烹飪專業綜合理論真題試卷
- 2025年電力人工智能多模態大模型創新技術及應用報告-西安交通大學
- 離婚協議書電子版下載
- 威海職業學院學籍檔案簿
- 蘇教版二年級數學下冊《第2單元 練習二》教學課件PPT小學公開課
- 長期購銷合作協議書參考
- 入團志愿書(2016版本)(可編輯打印標準A4) (1)
- 警棍盾牌術基本動作
- 撰寫課題申請書的五個關鍵(課堂PPT)
評論
0/150
提交評論