python基础知识整理 第六节:面向对象封装练习
PS:在python3中,object是所有類的基類。也就是說(shuō)只要我們定義了一個(gè)類,這個(gè)類最終的基類都是object類。(Object是python3中所有類的祖宗類)
所以在以后定義類時(shí),如果沒(méi)有父類建議統(tǒng)一繼承自object。
class 類名(object):pass
面向?qū)ο箝_(kāi)發(fā)的3大特性:封裝、繼承、多態(tài)。
1、針對(duì)Person類
2、針對(duì)于戶型添加家具(哪一個(gè)類要被使用到就應(yīng)該先開(kāi)發(fā)那個(gè)類)
class HouseItem:def __init__(self,name,area):self.Name=nameself.Area=areadef __str__(self):return "家具 %s 占地面積%.2f"%(self.Name,self.Area)
bed=HouseItem("席夢(mèng)思",130)
chest=HouseItem("衣柜",2)
table=HouseItem("餐桌",1.5)
print(bed)
print(chest)
print(table)class House:def __init__(self,house_type,area):#戶型和總面積應(yīng)該由外界傳遞self.House_type=house_typeself.Area=areaself.free_area=area#一個(gè)新房沒(méi)有任何家具,所以剩余面積就等于總面積(剩余面積不需要由外界傳遞)self.item_list=[]#新房子沒(méi)有家具初始的時(shí)候只是一個(gè)空列表,所以在定義形參的時(shí)候只需要為戶型和總面積傳遞兩個(gè)形參就可以def __str__(self):return ("該房子戶型%s,總面積%.2f,添加了%s家具,[該房子剩余面積]%.2f"%(self.House_type,self.Area,self.item_list,self.free_area)) def add_item(self,item):#判斷家具面積if item.Area>self.free_area:print("%s該家具放不下"%item.Name)return#只要return執(zhí)行下方的代碼就不會(huì)執(zhí)行#將家具的名稱添加到列表中self.item_list.append(item.Name)#計(jì)算剩余面積self.free_area-=item.Areamy_home=House("3室",120)
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)
結(jié)果:
3、(重點(diǎn):一個(gè)對(duì)象的屬性可以是另外一個(gè)類創(chuàng)建的對(duì)象)
class Gun:def __init__(self,model):self.Model=modelself.bullet_count=0def add_bullet(self,count):self.bullet_count+=countdef shoot(self):#判斷子彈數(shù)量if self.bullet_count<=0:print("%s沒(méi)有子彈了"%self.Model)return#發(fā)射子彈(-1)self.bullet_count-=1#提示發(fā)射子彈數(shù)量print("[%s]剩余子彈[%d]"%(self.Model,self.bullet_count))class Soldier:def __init__(self,name):self.Name=name#因?yàn)樾卤鴽](méi)有槍self.Gun=None#(使用None即定義屬性又不設(shè)置具體的搶對(duì)象)"""在初始化方法中定義這個(gè)屬性,避免了在給屬性添加對(duì)象時(shí),不要在外界添加這個(gè)屬性,而應(yīng)該在初始化方法內(nèi)部先把這個(gè)屬性添加好,如果想要修改這個(gè)屬性的值,我們?cè)僭谕獠渴褂觅x值語(yǔ)句給這個(gè)屬性設(shè)置一個(gè)新對(duì)象就可以""" def fire(self):#判斷自己是否有槍#if self.Gun==None:#==是比較變量的值是否相等的if self.Gun is None:#身份運(yùn)算符是用來(lái)比較內(nèi)存的地址的print("[%s]還沒(méi)有槍"%self.Name)return#槍裝子彈self.Gun.add_bullet(10)#發(fā)射子彈self.Gun.shoot()#創(chuàng)建槍對(duì)象
AK47=Gun("AK47")
#AK47.add_bullet(10)#槍自己并不能裝填子彈
#AK47.shoot()#槍自己并不能發(fā)射,需要士兵完成#創(chuàng)建許三多士兵對(duì)象
xusanduo=Soldier("許三多")
#在主程序中使用賦值語(yǔ)句給xusanduo賦值槍
xusanduo.Gun=AK47
xusanduo.fire()
print(xusanduo.Gun)
結(jié)果:
4、私有屬性和私有方法
在定義屬性和方法時(shí),在屬性名或者方法名前增加兩個(gè)下劃線,定義的就是私有屬性和方法。
私有屬性和方法的應(yīng)用場(chǎng)景就是:在實(shí)際開(kāi)發(fā)中對(duì)象的某些屬性和方法可能只希望在對(duì)象的內(nèi)部被使用,而不希望在外部被訪問(wèn)到。
PS:私有屬性只是禁止在外界訪問(wèn),而在對(duì)象的方法內(nèi)部仍然正常訪問(wèn)。
在對(duì)象的方法內(nèi)部是可以訪問(wèn)屬性以及自己的私有屬性的。在外界不能調(diào)用對(duì)象的私有屬性或者私有方法。
雖然子類對(duì)象不能在自己的方法內(nèi)部,直接訪問(wèn)父類的私有屬性和私有方法;但是子類對(duì)象可以通過(guò)父類的公有方法間接訪問(wèn)到私有屬性或者私有方法。
私有屬性、方法是對(duì)象的隱私,不對(duì)外公開(kāi),外界以及子類都不能間接訪問(wèn)。
私有屬性、方法通常用于做一些內(nèi)部的事情。
class Women:def __init__(self,name,age):self.Name=nameself.__Age=age#在對(duì)象的方法內(nèi)部,是可以訪問(wèn)對(duì)象的私有屬性的def secret(self):print("%s的年齡是%d"%(self.Name,self.__Age))
xiaofang=Women("小芳",18)
#私有屬性,在外界不能夠被直接訪問(wèn)
#print(xiaofang.__Age)#報(bào)錯(cuò):'Women' object has no attribute '__Age'
xiaofang.secret()#輸出:小芳的年齡是18(在對(duì)象的方法內(nèi)部,是可以訪問(wèn)對(duì)象的私有屬性的)
5、繼承:子類擁有父類的所有方法和屬性
繼承的語(yǔ)法:
class 類名(父類名):pass
子類繼承自父類,可以直接享受父類中已經(jīng)封裝好的方法,不需要再次開(kāi)發(fā)。
子類中應(yīng)該根據(jù)職責(zé),封裝子類特有的屬性和方法。
PS:父類私有的屬性和方法,是屬于父類的;子類是無(wú)法訪問(wèn)到的。但是子類對(duì)象可以通過(guò)父類的公有方法間接訪問(wèn)到私有屬性或者私有方法。
5.1覆蓋父類的方法
父類中封裝的方法不能滿足子類的需要時(shí),可以對(duì)方法進(jìn)行重寫(xiě)。(對(duì)父類的方法進(jìn)行重寫(xiě)是完全覆蓋了父類的方法)
具體的方式就是:在子類中定義一個(gè)和父類同名的方法并且實(shí)現(xiàn)。重寫(xiě)之后在運(yùn)行時(shí),只會(huì)調(diào)用子類中重寫(xiě)的方法,而不會(huì)調(diào)用父類封裝的方法。
5.2對(duì)父類的方法進(jìn)行擴(kuò)展
如果在開(kāi)發(fā)中,子類的方法實(shí)現(xiàn)中,包含父類的方法實(shí)現(xiàn)。(也就是說(shuō)父類原本封裝的方法實(shí)現(xiàn)是子類方法的一部分,但是父類的方法只能滿足子類方法所需的一部分功能,這個(gè)時(shí)候就需要使用擴(kuò)展的方式,在子類中對(duì)父類的方法進(jìn)行一個(gè)擴(kuò)展補(bǔ)充)
擴(kuò)展的方式:(在子類中對(duì)父類的方法進(jìn)行擴(kuò)展,但是仍然保留了父類中的方法,沒(méi)有完全覆蓋)
- 在子類中重寫(xiě)父類的方法。
- 在這個(gè)方法中,在需要的位置使用super().父類方法來(lái)調(diào)用父類方法的執(zhí)行。
- 代碼其他的位置針對(duì)子類的需求,編寫(xiě)子類特有的代碼實(shí)現(xiàn)。
關(guān)于super:
- 在python中super是一個(gè)特殊的類。
- super()就是使用super類創(chuàng)建出來(lái)的對(duì)象。(super類后邊跟這個(gè)一個(gè)小括號(hào)可以創(chuàng)建對(duì)象)
- 最常使用的場(chǎng)景就是在重寫(xiě)父類方法時(shí),調(diào)用在父類中封裝的方法實(shí)現(xiàn)。
class Animal:def eat(self):print("動(dòng)物會(huì)吃")def drink(self):print("動(dòng)物會(huì)喝")def bark(self):print("動(dòng)物會(huì)叫")
class Dog(Animal):def swim(self):print("狗會(huì)游泳")def bark(self):print("狗會(huì)汪汪叫")
class XiaoTianQuan(Dog):def fly(self):print("哮天犬會(huì)飛")def bark(self):#1、針對(duì)子類特有的需求編寫(xiě)代碼print("我是哮天犬,比一般的狗叫的更大聲")#2、使用super().調(diào)用原來(lái)在父類中封裝的方法super().bark()#如果把super方法注釋掉,就不會(huì)調(diào)用到父類的方法了"""如果在子類中需要用到父類的方法,那么我們就在子類中使用super()這個(gè)特殊的對(duì)象來(lái)調(diào)用父類方法的實(shí)現(xiàn);而在其他的位置我們就可以根據(jù)子類特有的需求來(lái)編寫(xiě)特有的代碼就可以"""#3、增加其他子類的代碼print("我是神狗")
xtq=XiaoTianQuan()
xtq.bark()
結(jié)果:
6、多繼承
上述定義子類的小括號(hào)內(nèi)只有一個(gè)父類,我們叫做單繼承。而在python中,子類是可以擁有多個(gè)父類的,并且具有所有父類的屬性和方法。
語(yǔ)法:
class 子類(父類1,父類2...):pass
Q:如果不同的父類中,存在同名的方法,子類對(duì)象在調(diào)用方法時(shí),會(huì)調(diào)用哪一個(gè)父類的方法?
A:首先在開(kāi)發(fā)時(shí)應(yīng)該盡量避免這種混淆的情況;如果父類之間存在同名的屬性和方法,應(yīng)該盡量避免使用多繼承。(如果非要一樣的話,那么是根據(jù)先后的繼承順序來(lái)執(zhí)行的,小括號(hào)內(nèi)的父類哪個(gè)在前調(diào)用哪個(gè))
7、多態(tài)
一個(gè)是調(diào)用子類的方法,一個(gè)是調(diào)用父類中的方法。
8、類中的術(shù)語(yǔ):
PS:假如我們使用class關(guān)鍵字定義了一個(gè)類,程序在運(yùn)行時(shí)這個(gè)類會(huì)不會(huì)被加載到內(nèi)存呢?應(yīng)該會(huì)的。假設(shè)我們?cè)诙x一個(gè)類之后,在程序運(yùn)行時(shí)是不是可以使用這個(gè)類來(lái)創(chuàng)建出很多很多個(gè)對(duì)象,在對(duì)象的內(nèi)存空間中保存的是什么內(nèi)容呢?在對(duì)象的內(nèi)存空間中保存的是不同對(duì)象各自不同的屬性,而對(duì)象的實(shí)例方法是保存在類所在的內(nèi)存空間的,當(dāng)我們讓某一個(gè)對(duì)象調(diào)用實(shí)例方法時(shí),這個(gè)對(duì)象會(huì)把自己的引用當(dāng)做參數(shù)傳遞給這個(gè)方法,因此對(duì)象的實(shí)例方法是保存在類所在的內(nèi)存空間的,類在運(yùn)行的時(shí)候同樣也會(huì)被加載到內(nèi)存。、
class? ABC:#定義的類屬于類對(duì)象。
object1=ABC()#屬于實(shí)例對(duì)象。
除了可以封裝實(shí)例的屬性和方法之外,也可以訪問(wèn)類的屬性或者調(diào)用類的方法。(因?yàn)轭愂且粋€(gè)特殊的對(duì)象,可以擁有自己的屬性和方法,即類屬性、類方;所以可以通過(guò)類名.的方式訪問(wèn)類的屬性或者調(diào)用類的方法)(還有一種訪問(wèn)類屬性的方式但是不推薦使用,對(duì)象.類屬性)
1、可以使用賦值語(yǔ)句定義類屬性。
定義類屬性。
2、定義類方法
3、靜態(tài)方法
通過(guò)類名.調(diào)用靜態(tài)方法,不需要?jiǎng)?chuàng)建對(duì)象。
9、綜合示例演示
class Game(object):top_score=100#類屬性@staticmethoddef show_help():print("幫助信息")@classmethoddef show_top_score(cls):print("這個(gè)游戲的歷史最高分是%d"%cls.top_score)def __init__(self,name):self.player_name=name#實(shí)例屬性def start_game(self):print("%s可以開(kāi)始游戲了"%self.player_name)
#查看游戲的幫助信息
Game.show_help()
#查看歷史最高分
Game.show_top_score()
#穿件游戲?qū)ο?chiji=Game("小明")
chiji.start_game()
結(jié)果:
??
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的python基础知识整理 第六节:面向对象封装练习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Paper8:Spatial Pyram
- 下一篇: python基础知识整理 第七节:单例设