上一篇提到過類的屬性,但沒有詳細介紹,本篇詳細介紹一下類的屬性 一 、類的屬性 方法是用來操作數據的,而屬性則是建模必不的內容,而且操作的數據,大多數是屬性,比如游戲中的某個boss類,它的生命值就是屬性(不同級別的boss,有不同的生命值),被攻擊方法(不同的攻擊,傷害值不同),當boss被攻擊時 ...
上一篇提到過類的屬性,但沒有詳細介紹,本篇詳細介紹一下類的屬性
一 、類的屬性
方法是用來操作數據的,而屬性則是建模必不的內容,而且操作的數據,大多數是屬性,比如游戲中的某個boss類,它的生命值就是屬性(不同級別的boss,有不同的生命值),被攻擊方法(不同的攻擊,傷害值不同),當boss被攻擊時,通過被攻擊方法來減少boss自身的生命值,從而改變boss類的生命值屬性。
python中類的屬性有兩類:實例屬性和類屬性 面向對象編程最大好處就是通過繼承來減少代碼,同時可以定製新類。類的繼承,創建的新類稱為了類,被繼承的類為父類。子類繼承父類後,子類就具有父類的屬性和方法,但不能繼承父類的私有屬性和私有方法(屬性名或方法名以兩個下畫線開頭的),子類可以通過重載來修改父類的方法,以實現與父類不同的行為表現或能力。
下麵通過一個代碼實例,進行介紹,代碼如下:
class Demo_Property: #定義類 class_name = "Demo_Property" #類屬性 def __init__ (self,x=0): #實例屬性 self.x = x def class_info(self): #輸出信息方法 print("類變數值:",Demo_Property.class_name) print("實例變數值:",self.x) def chng(self,x): #修改實例屬性的方法 self.x=x #註意實例屬性的引用方式 def chng_cn(self,name): #修改類屬性的方法 Demo_Property.class_name = name #註意類屬性引用方式 dpa = Demo_Property() #創建一個對象dpa,也就是實例化類 dpb = Demo_Property() #創建一個對象dpb,即實例化類 print('初始化兩個實例') dpa.class_info() dpb.class_info() print('修改實例變數') print('修改dpa 實例變數\n') dpa.chng(3) dpa.class_info() dpb.class_info() print('修改dpb實例變數\n') dpb.chng(10) dpa.class_info() dpb.class_info print('修改類變數') print('修改 dpa類變數\n') dpa.chng_cn ('dpa') dpa.class_info() dpb.class_info() print('修改dpb實例變數\n') dpb.chng_cn ('dpb') dpa.class_info() dpb.class_info()
代碼說明:第一行定義Demo_property類,第二行class_name = "Demo_Property" #定義了類的屬性class_name,接下來的兩行,定義了實例屬性x,
後面三個def 分別定義了一個輸入信息的方法class_info,一個修改實例屬性的方法chng,一個修改類屬性的方法chng_cn。再創建了兩個實例dpa和dpb。
dpa.class_info()和dpb.class_info()分別調用class_info()方法分別列印類變數值和實例變數值。後面的幾行,分別通過修改變數,來實現實例變數、類變數的變化。運行結果如下:
二、類成員方法與靜態方法
和屬性一樣,類的方法也有不同類型,主要有實例方法、類方法、靜態方法。上述所有類中的方法都是實例方法,隱含調用參數是類的實例,類方法隱含調用的是類,靜態方法沒有隱含參數。
類方法和靜態方法的定義方式與實例方法不同,調用方式也不相同。
靜態方法定義的時候用裝飾器@staticmethod進行修飾,沒有預設參數
類方法定義時應用裝飾器@classmethod進行修飾,必須有預設參數“cls”,兩者調用方式可以直接由類名進行,既可用該類的任一個實例進行調用 ,也可以在
實例化前調用。如下例子:
class DemoMthd: @staticmethod #靜態方法裝飾器 def static_mthd(): #定義一個靜態類 print("調用了靜態方法!") @classmethod #類方法裝飾器 def class_mthd(cls): #類方法定義,帶預設參數cls print("調用了類方法!") DemoMthd.static_mthd() #未實例化類,通過類名調用靜態方法 DemoMthd.class_mthd() #未實例化類,通過類名調用類方法 dm = DemoMthd () #創建對象,實例化 dm.static_mthd() #通過實例調用靜態方法 dm.class_mthd() #通過實例調用類方法
註意:仔細分析上面代碼中的註釋。運行結果如下:
三、類的繼承
通過上述例子,可以看出,我們在創建dpa和dpb時(其他例子中的多個對象),只通過實例化就創建了具體相同結構的對象,這就是面向對象編程的好處:減少代碼量。
但如果dpa,dpb大部分結構相同,但又有所不同,比如游戲中的不同級別的boss,小boss,只有砍的攻擊方法,而大boss,除了砍,還有噴火、掃腿……等不同的攻擊方法(如上一篇中的,走、唱、跑方法一樣),該如何處理?這就需要用到類的繼承。類的繼承,不僅可以減少代碼量,同時還可以定製新類。
類的繼承,創建的新類稱為子類,被繼承的類為父類。子類繼承父類後,子類就具有父類的屬性和方法,但不能繼承父類的私有屬性和私有方法(屬性名或方法名以兩個下畫線開頭的),子類可以通過重載(後面會演示)來修改父類的方法,以實現與父類不同的行為表現或能力。
那我們可以思考一下,將上一篇中的cat進行更加抽象成一個新類animal,然後cat的繼承animal的屬性,於是得到以下代碼:
# -*- coding: utf-8 -*- """ Created on Sat Sep 16 19:59:24 2023 @author: Administrator """ def coord_chng(x,y): #定義一個全局函數,模擬坐標值變換 return (abs(x),abs(y)) #將x,y 值求絕對值後返回 class Animal: def __init__ (self,lifevalue): self.lifevalue=lifevalue def info(self): #定義一個方法 print("當前位置:(%d,%d)"% (self.x,self.y)) def crawl(self,x,y): self.x=x self.y=y print("爬行……") self.info() def move(self,x,y): #定義一個方法move() x,y = coord_chng(x,y) #調用全局函數,坐標變換 self.edit_point(x,y) #調用類中的方法edit_point() self.disp_point() #調用類中的方法disp_point() def edit_point(self,x,y): #定義一個方法 self.x += x self.y += y def disp_point(self): #定義一個方法 print("當前位置:(%d,%d)"% (self.x,self.y)) class Cat(Animal): #定義一個類Cat類,繼承類Animal def __init__ (self,x=0,y=0,color="white"): #定義一個構造方法 self.x=x self.y=y self.color=color #新增加一個顏色 self.disp_point() #構造函數中調用類中的方法disp_point() def run(self,x,y): #定義一個方法run() x,y = coord_chng(x,y) #調用全局函數,坐標變換 self.edit_point(x,y) #調用類中的方法edit_point() self.disp_point() #調用類中的方法disp_point() cat_a= Cat() #實例化Cat()類 cat_a.move(2,4) #調用cat_a實例的方法move() cat_a.move(-9,6) #調用cat_a實例的方法move() cat_a.move(12,-16)#調用cat_a實例的方法move() cat_a.run(12,-16) #調用cat_a實例的方法run()
註意紅色註釋部分,move()這個方法是Cat類沒有的,但在Animal中有,Cat類通過繼承Animal類,獲得了Animal中move方法。
同樣,也可以將上篇中的Person類繼承Animal類的功能,併進行少量修改,全部代碼如下:
# -*- coding: utf-8 -*- """ Created on Sun Sep 17 19:59:24 2023 @author: Administrator """ def coord_chng(x,y): #定義一個全局函數,模擬坐標值變換 return (abs(x),abs(y)) #將x,y 值求絕對值後返回 class Animal: def __init__ (self,lifevalue): self.lifevalue=lifevalue def info(self): #定義一個方法 print("當前位置:(%d,%d)"% (self.x,self.y)) def crawl(self,x,y): self.x=x self.y=y print("爬行……") self.info()
def move(self,x,y): #定義一個方法move() x,y = coord_chng(x,y) #調用全局函數,坐標變換 self.edit_point(x,y) #調用類中的方法edit_point() self.disp_point() #調用類中的方法disp_point() def edit_point(self,x,y): #定義一個方法 self.x += x self.y += y def disp_point(self): #定義一個方法 print("當前位置:(%d,%d)"% (self.x,self.y)) class Cat(Animal): #定義一個類Cat類,繼承類Animal def __init__ (self,x=0,y=0,color="white"): #定義一個構造方法 self.x=x self.y=y self.color=color #新增加一個顏色 self.disp_point() #構造函數中調用類中的方法disp_point() class Person(Animal): #定義一個類Person類,繼承類Animal def __init__(self,new_name,x,y,new_age,new_hight,new_weight,edu_certification,new_job): #self.name = "Tom" self.x=x self.y=y self.name=new_name self.age=new_age self.hight=new_hight self.weight=new_weight self.edu_certif=edu_certification self.job=new_job def eat(self): # 哪一個對象調用的方法,self就是哪一個對象的引用 print("%s 愛吃魚" % self.name) def drink(self): print("%s 要喝水" % self.name) def walk(self): print("%s今天步行了10公裡"%self.name) def run(self): # 必須返回一個字元串 return "%s跑了10公裡,用時56分鐘。" % self.name def sing(self): # 必須返回一個字元串 return "%s唱了一首《我的中國心》" % self.name def working(self): # 必須返回一個字元串 return "%s工作了很久!" % self.name tom=Person("Tom",10,20,24,175,70,"bachelor","writer") #lucy=Person("Lucy") #lily=Person("Lily") print("%s的身高是%s cm\n" %(tom.name,tom.hight)) print("%s的體重是%sKG\n" %(tom.name,tom.weight)) print(tom.sing()) print(tom.run()) tom.move(2,4) tom.move(10,-12) print("------------------顯示分隔線--------------------\n") cat_a= Cat() #實例化Cat()類 cat_a.move(2,4) #調用cat_a實例的方法move() cat_a.move(12,-16)#調用cat_a實例的方法move()
代碼中紅色部分為修改。可以看出,tom繼承Animal類後,也繼承了move()方法。運行結果:
四、類的多重繼承
python編程中,一個類不僅可以繼承一個類,還可以繼承多個類,即多重繼承。和上述所講繼承一樣,只不過在括弧中,用“,”分隔開。可以當作思考題,自動動手,比如利用上述的person類,Cat類,創建一個怪物類,然後實例化。
五、方法的重載
當子類繼承父類時,子類如果要想修改父類的行為,則應使用方法重載來實現,
方法重載:在子類中定義一個和所繼承的父類中,同名的方法。
比如,上述代碼中animal類中有一個move()方法,如果將子類Person中的def run(self) 修改為def move(self),即move()方法被 重載了
當用子類Person創建對象(實例化)後,調用的是Person類中的move()。
同樣,如果在多重繼承中,兩個父類具有同名方法,為避免不要求的錯誤,在子類中對該方法進行重載。
翻譯
搜索
複製