面向對象編程介紹
面向對象(object-oriented ;簡稱: OO) 至今還沒有統一的概念,我這里把它定義為: 按人們認識客觀世界的系統思維方式,采用基于對象(實體)的概念建立模型,模擬客觀世界分析、設計、實現軟件的辦法。
面向對象編程(Object Oriented Programming-OOP) 是一種解決軟件復用的設計和編程方法。這種方法把軟件系統中相近相似的操作邏輯和操作應用數據、狀態,以類的型式描述出來,以對象實例的形式在軟件系統中復用,以達到提高軟件開發效率的作用。
類和對象
面向對象編程的2個非常重要的概念:類和對象。
- 對象是面向對象編程的核心,在使用對象的過程中,為了將具有共同特征和行為的一組對象抽象定義,提出了另外一個新的概念——類。
- 類就相當于制造飛機時的圖紙,用它來進行創建的飛機就相當于對象。
類
具有相似內部狀態和運動規律的實體的集合(或統稱為抽象)。具有相同屬性和行為事物的統稱。類是抽象的,在使用的時候通常會找到這個類的一個具體的存在,使用這個具體的存在。一個類可以找到多個對象。
對象
某一個具體事物的存在 ,在現實世界中可以是看得見摸得著的,可以是直接使用的。
類和對象之間的關系
類就是創建對象的模板。
類的構成
類(Class) 由3個部分構成:
- 類的名稱:類名
- 類的屬性:一組數據
- 類的方法:允許對進行操作的方法 (行為)
示例:狗類
- 類名:狗(Dog)
- 屬性:品種 、毛色、性別、名字、 腿兒的數量
- 方法(行為/功能):叫 、跑、咬人、吃、搖尾巴
類的抽象
擁有相同(或者類似)屬性和行為的對象都可以抽像出一個類。
定義類
定義一個類,格式如下:
class 類名:
方法列表
示例:定義一個Car類
# 定義類
class Car:
# 方法
def getCarInfo(self):
print('車輪子個數:%d, 顏色%s'%(self.wheelNum, self.color))
def move(self):
print("車正在移動...")
說明:
- 定義類時有2種:新式類和經典類,上面的Car為經典類,如果是Car(object)則為新式類;
- 類名的命名規則按照"大駝峰"。
創建對象
python中,可以根據已經定義的類去創建出一個個對象。
創建對象的格式為:
對象名 = 類名()
創建對象的示例:
# 定義類
class Car:
# 移動
def move(self):
print('車在奔跑...')
# 鳴笛
def toot(self):
print("車在鳴笛...嘟嘟..")
# 創建一個對象,并用變量BMW來保存它的引用
BMW = Car()
BMW.color = '黑色'
BMW.wheelNum = 4 #輪子數量
BMW.move()
BMW.toot()
print(BMW.color)
print(BMW.wheelNum)
總結:
- BMW = Car(),這樣就產生了一個Car的實例對象,此時也可以通過實例對象BMW來訪問屬性或者方法;
- 第一次使用BMW.color = '黑色'表示給BMW這個對象添加屬性,如果后面再次出現BMW.color = xxx表示對屬性進行修改;
- BMW是一個對象,它擁有屬性(數據)和方法(函數);
- 當創建一個對象時,就是用一個模子,來制造一個實物 。
__ init __()方法
我們已經給BMW這個對象添加了2個屬性,wheelNum(車的輪胎數量)以及color(車的顏色),試想如果再次創建一個對象的話,肯定也需要進行添加屬性,顯然這樣做很費事,那么有沒有辦法能夠在創建對象的時候,就順便把車這個對象的屬性給設置呢?我們可以用__ init __()方法實現這一點。
使用方式
def 類名:
#初始化函數,用來完成一些默認的設定
def __init__():
pass
__init __()方法的調用
# 定義汽車類
class Car:
def __init__(self):
self.wheelNum = 4
self.color = '藍色'
def move(self):
print('車在跑,目標:夏威夷')
# 創建對象
BMW = Car()
print('車的顏色為:%s'%BMW.color)
print('車輪胎數量為:%d'%BMW.wheelNum)
結果:
車的顏色為:blue
車輪胎數量為:4
總結:
當創建Car對象后,在沒有調用__ init__()方法的前提下,BMW就默認擁有了2個屬性wheelNum和color,原因是__ init__()方法是在創建對象后,就立刻被默認調用了。
傳參
既然在創建完對象后__ init__()方法已經被默認的執行了,那么能否讓對象在調用__ init__()方法的時候傳遞一些參數呢?如果可以,那怎樣傳遞呢?
# 定義汽車類
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def move(self):
print('車在跑,目標:夏威夷')
# 創建對象
BMW = Car(4, 'green')
print('車的顏色為:%s'%BMW.color)
print('車輪子數量為:%d'%BMW.wheelNum)
結果:
車的顏色為:green
車輪胎數量為:4
總結:
- __ init__()方法,在創建一個對象時默認被調用,不需要手動調用;
- __ init__(self)中,默認有1個參數名字為self,如果在創建對象時傳遞了2個實參,那么__init __(self)中出了self作為第一個形參外還需要2個形參,例如__init __(self,x,y);
- __ init__(self)中的self參數,不需要開發者傳遞,python解釋器會自動把當前的對象引用傳遞進去。
self
理解self
如下示例:
# 定義一個類
class Animal:
# 方法
def __init__(self, name):
self.name = name
def printName(self):
print('名字為:%s'%self.name)
# 定義一個函數
def myPrint(animal):
animal.printName()
dog1 = Animal('西西')
myPrint(dog1)
dog2 = Animal('北北')
myPrint(dog2)
運行結果:
名字為:西西
名字為:北北
總結:
- 所謂的self,可以理解為自己;
- 可以把self當做Java中類里面的this指針一樣理解,就是對象自身的意思;
- 某個對象調用其方法時,python解釋器會把這個對象作為第一個參數傳遞給self,所以開發者只需要傳遞后面的參數即可。
舉個例子:老王開槍
人類
- 屬性
- 姓名
- 血量
- 持有的槍
- 方法
- 安子彈
- 安彈夾
- 拿槍(持有搶)
- 開槍
子彈類
- 屬性
- 殺傷力
- 方法
- 傷害敵人(讓敵人掉血)
彈夾類
- 屬性
- 容量(子彈存儲的最大值)
- 當前保存的子彈
- 方法
- 保存子彈(安裝子彈的時候)
- 彈出子彈(開槍的時候)
槍類
- 屬性
- 彈夾(默認沒有彈夾,需要安裝)
- 方法
- 連接彈夾(保存彈夾)
- 射子彈
人類實現:
class Ren:
def __init__(self,name):
self.name = name
self.xue = 100
self.qiang = None
def __str__(self):
return self.name + "剩余血量為:" + str(self.xue)
def anzidan(self,danjia,zidan):
danjia.baocunzidan(zidan)
def andanjia(self,qiang,danjia):
qiang.lianjiedanjia(danjia)
def naqiang(self,qiang):
self.qiang = qiang
def kaiqiang(self,diren):
self.qiang.she(diren)
def diaoxue(self,shashangli):
self.xue -= shashangli
彈夾類實現:
class Danjia:
def __init__(self, rongliang):
self.rongliang = rongliang
self.rongnaList = []
def __str__(self):
return "彈夾當前的子彈數量為:" + str(len(self.rongnaList)) + "/" + str(self.rongliang)
def baocunzidan(self,zidan):
if len(self.rongnaList) < self.rongliang:
self.rongnaList.append(zidan)
def chuzidan(self):
#判斷當前彈夾中是否還有子彈
if len(self.rongnaList) > 0:
#獲取最后壓入到單間中的子彈
zidan = self.rongnaList[-1]
self.rongnaList.pop()
return zidan
else:
return None
子彈類實現:
class Zidan:
def __init__(self,shashangli):
self.shashangli = shashangli
def shanghai(self,diren):
diren.diaoxue(self.shashangli)
槍類實現:
class Qiang:
def __init__(self):
self.danjia = None
def __str__(self):
if self.danjia:
return "槍當前有彈夾"
else:
return "槍沒有彈夾"
def lianjiedanjia(self,danjia):
if not self.danjia:
self.danjia = danjia
def she(self,diren):
zidan = self.danjia.chuzidan()
if zidan:
zidan.shanghai(diren)
else:
print("沒有子彈了,放了空槍....")
調用運行:
#創建一個人對象
laowang = Ren("老王")
#創建一個彈夾
danjia = Danjia(20)
print(danjia)
#循環的方式創建一顆子彈,然后讓老王把這顆子彈壓入到彈夾中
i=0
while i<5:
zidan = Zidan(5)
laowang.anzidan(danjia,zidan)
i+=1
#測試一下,安裝完子彈后,彈夾中的信息
print(danjia)
#創建一個槍對象
qiang = Qiang()
print(qiang)
#讓老王,把彈夾連接到槍中
laowang.andanjia(qiang,danjia)
print(qiang)
#創建一個敵人
diren = Ren("敵人")
print(diren)
#讓老王拿起槍
laowang.naqiang(qiang)
#老王開槍射敵人
laowang.kaiqiang(diren)
print(diren)
print(danjia)