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