python版,面向對象編程分三篇給大家介紹,這是第一篇,歡迎閱讀學習,一起進步
Python專欄請參考
:人生苦短-我學python
一.面向對象編程介紹
- 如今主流的軟件開發思想有兩種:一個是面向過程,另一個是面向對象。面向過程出現得較早,典型代表爲C語言,開發中小型項目的效率很高,但是很難適用於如今主流的大中型項目開發場景。面向對象則出現得更晚一些,典型代表爲Java或C++等語言,更加適合用於大型開發場景。兩種開發思想各有長短。
- 對於面向過程的思想: 需要實現一個功能的時候,看重的是開發的步驟和過程,每一個步驟都需要自己親力親爲,需要自己編寫代碼(自己來做)
- 對於面向對象的思想:當需要實現一個功能的時候,看重的並不是過程和步驟,而是關心誰幫我做這件事(偷懶,找人幫我做)
- 面向對象的三大特徵有:封裝性、繼承性、多態性。
生活舉例
-
洗衣服
-
面向過程(手洗)
:脫衣服、找一個盆、加水、加洗衣粉、浸泡30分鐘、搓洗、擰衣服、倒掉水、再加水、漂洗、擰衣服、倒掉水、晾衣服。 -
面向對象(機洗)
:脫衣服、放入洗衣機、按下開關、拿出衣服晾曬。 -
買電腦
-
面向過程(自己買)
:需要電腦、查詢參數信息、橫向比較機型、瞭解打折信息、與店家討價還價、下單、收快遞、開機驗貨、確認收貨。 -
面向對象(找人買)
:需要電腦、找祕書幫我買、收電腦。
二.類和對象
面向對象編程的2個非常重要的概念:類和對象
- 對象是面向對象編程的核心,在使用對象的過程中,爲了將具有共同特徵和行爲的一組對象抽象定義,提出了另外一個新的概念——類
- 面向對象的語言當中,“類”就是用來模擬現實事物的。
類:抽象的,是一張“手機設計圖”。
對象:具體的,是一個“真正的手機實例”。
- 小結:類是抽象的,在使用的時候通常會找到這個類的一個具體的存在,使用這個具體的存在。一個類可以找到多個對象。
人以類聚 物以羣分。
具有相似內部狀態和運動規律的實體的集合(或統稱爲抽象)。
具有相同屬性和行爲事物的統稱
- 類就相當於製造飛機時的圖紙,用它來進行創建的飛機就相當於對象
類是一類事物,對象即是這類事物實現
- 類中也有屬性、行爲兩個組成部分,而“對象”是類的具體實例
- 屬性:事物的特徵描述信息,用於描述某個特徵“是什麼”。
- 行爲:事物的能力行動方案,用於說明事物“能做什麼”。
三.類的構成
- 類(Class) 由3個部分構成
類的名稱:類名
類的屬性:一組數據
類的方法:允許對進行操作的方法 (行爲)
案例
1)人類設計:
事物名稱(類名):人(Person)
屬性:身高(height)、年齡(age)
方法(行爲/功能):跑(run)、打架(fight)
2)狗類的設計
類名:狗(Dog)
屬性:品種 、毛色、性別、名字、 腿兒的數量
方法(行爲/功能):叫 、跑、咬人、吃、搖尾巴
- 類的抽象
- 如何把日常生活中的事物抽象成程序中的類?
擁有相同(或者類似)屬性和行爲的對象都可以抽像出一個類
- 方法:一般名詞都是類(名詞提煉法)
案例:坦克發射3顆炮彈轟掉了2架飛機
- 坦克—可以抽象成類
- 炮彈—以抽象成類
- 飛機—可以抽象成類
案例:如下植物大戰殭屍可以抽象爲幾個類
向日葵
類名: xrk
屬性: 顏色
行爲: 放陽光
豌豆
類名: wd
屬性: 顏色 、髮型,血量
行爲:發炮, 搖頭
堅果:
類名:jg
屬性:血量 類型
行爲:阻擋;
殭屍:
類名:js
屬性:顏色、血量、 類型、速度
行爲:走 跑跳 吃 死
四.定義類 和 創建對象
- 定義一個類,格式如下:
class 類名:
方法列表
- demo:定義一個Hero類
# class Hero: # 經典類(舊式類)定義形式
# class Hero():
class Hero(object): # 新式類定義形式
def info(self):
print("英雄各有見,何必問出處。")
- 說明:
- ①定義類時有2種形式:新式類和經典類,上面代碼中的Hero爲新式類,前兩行註釋部分則爲經典類;
- ②object 是Python 裏所有類的最頂級父類;
- ③類名 的命名規則按照
"大駝峯命名法"
; - ④info 是一個實例方法,第一個參數一般是self,表示實例對象本身,當然了可以將self換爲其它的名字,其作用是一個變量這個變量指向了實例對象
- python中,可以根據已經定義的類去創建出一個或多個對象。
- 創建對象的格式爲:
對象名1 = 類名()
對象名2 = 類名()
對象名3 = 類名()
- 創建對象demo:
class Hero(object): # 新式類定義形式
"""info 是一個實例方法,類對象可以調用實例方法,實例方法的第一個參數一定是self"""
def info(self):
"""當對象調用實例方法時,Python會自動將對象本身的引用做爲參數,
傳遞到實例方法的第一個參數self裏"""
print(self)
print("self各不同,對象是出處。")
# Hero這個類 實例化了一個對象 taidamier(泰達米爾)
taidamier = Hero()
# 對象調用實例方法info(),執行info()裏的代碼
# . 表示選擇屬性或者方法
taidamier.info()
print(taidamier) # 打印對象,則默認打印對象在內存的地址,結果等同於info裏的print(self)
print(id(taidamier)) # id(taidamier) 則是內存地址的十進制形式表示
<__main__.Hero object at 0x036EB0D0>
self各不同,對象是出處。
<__main__.Hero object at 0x036EB0D0>
57585872
- 小結:當創建一個對象時,就是用一個模子,來製造一個實物
五.對象屬性獲取
對象既然有實例方法,是否也可以有自己的屬性?
- 添加和獲取對象的屬性
class Hero(object):
"""定義了一個英雄類,可以移動和攻擊"""
def move(self):
"""實例方法"""
print("正在前往事發地點...")
def attack(self):
"""實例方法"""
print("發出了一招強力的普通攻擊...")
# 實例化了一個英雄對象 泰達米爾
taidamier = Hero()
# 給對象添加屬性,以及對應的屬性值
taidamier.name = "泰達米爾" # 姓名
taidamier.hp = 2600 # 生命值
taidamier.atk = 450 # 攻擊力
taidamier.armor = 200 # 護甲值
# 通過.成員選擇運算符,獲取對象的屬性值
print("英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp))
print("英雄 %s 的攻擊力 :%d" % (taidamier.name, taidamier.atk))
print("英雄 %s 的護甲值 :%d" % (taidamier.name, taidamier.armor))
# 通過.成員選擇運算符,獲取對象的實例方法
taidamier.move()
taidamier.attack()
英雄 泰達米爾 的生命值 :2600
英雄 泰達米爾 的攻擊力 :450
英雄 泰達米爾 的護甲值 :200
正在前往事發地點...
發出了一招強力的普通攻擊...
對象創建並添加屬性後,能否在類的實例方法裏獲取這些屬性呢?如果可以的話,應該通過什麼方式?
- 在方法內通過self獲取對象屬性
class Hero(object):
"""定義了一個英雄類,可以移動和攻擊"""
def move(self):
"""實例方法"""
print("正在前往事發地點...")
def attack(self):
"""實例方法"""
print("發出了一招強力的普通攻擊...")
def info(self):
"""在類的實例方法中,通過self獲取該對象的屬性"""
print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))
# 實例化了一個英雄對象 泰達米爾
taidamier = Hero()
# 給對象添加屬性,以及對應的屬性值
taidamier.name = "泰達米爾" # 姓名
taidamier.hp = 2600 # 生命值
taidamier.atk = 450 # 攻擊力
taidamier.armor = 200 # 護甲值
# 通過.成員選擇運算符,獲取對象的實例方法
taidamier.info() # 只需要調用實例方法info(),即可獲取英雄的屬性
taidamier.move()
taidamier.attack()
英雄 泰達米爾 的生命值 :2600
英雄 泰達米爾 的攻擊力 :450
英雄 泰達米爾 的護甲值 :200
正在前往事發地點...
發出了一招強力的普通攻擊...
六.魔法方法__init__()
創建對象後再去添加屬性有點不合適,有沒有簡單的辦法,可以在創建對象的時候,就已經擁有這些屬性?
class Hero(object):
"""定義了一個英雄類,可以移動和攻擊"""
# Python 的類裏提供的,兩個下劃線開始,兩個下劃線結束的方法,就是魔法方法,__init__()就是一個魔法方法,通常用來做屬性初始化 或 賦值 操作。
# 如果類面沒有寫__init__方法,Python會自動創建,但是不執行任何操作,
# 如果爲了能夠在完成自己想要的功能,可以自己定義__init__方法,
# 所以一個類裏無論自己是否編寫__init__方法 一定有__init__方法。
def __init__(self):
""" 方法,用來做變量初始化 或 賦值 操作,在類實例化對象的時候,會被自動調用"""
self.name = "泰達米爾" # 姓名
self.hp = 2600 # 生命值
self.atk = 450 # 攻擊力
self.armor = 200 # 護甲值
def info(self):
"""在類的實例方法中,通過self獲取該對象的屬性"""
print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))
def move(self):
"""實例方法"""
print("正在前往事發地點...")
def attack(self):
"""實例方法"""
print("發出了一招強力的普通攻擊...")
# 實例化了一個英雄對象,並自動調用__init__()方法
taidamier = Hero()
# 通過.成員選擇運算符,獲取對象的實例方法
taidamier.info() # 只需要調用實例方法info(),即可獲取英雄的屬性
taidamier.move()
taidamier.attack()
英雄 泰達米爾 的生命值 :2600
英雄 泰達米爾 的攻擊力 :450
英雄 泰達米爾 的護甲值 :200
正在前往事發地點...
發出了一招強力的普通攻擊...
- 有參數的__init__()方法
class Hero(object):
"""定義了一個英雄類,可以移動和攻擊"""
def __init__(self, name, skill, hp, atk, armor):
""" __init__() 方法,用來做變量初始化 或 賦值 操作"""
# 英雄名
self.name = name
# 技能
self.skill = skill
# 生命值:
self.hp = hp
# 攻擊力
self.atk = atk
# 護甲值
self.armor = armor
def move(self):
"""實例方法"""
print("%s 正在前往事發地點..." % self.name)
def attack(self):
"""實例方法"""
print("發出了一招強力的%s..." % self.skill)
def info(self):
print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))
# 實例化英雄對象時,參數會傳遞到對象的__init__()方法裏
taidamier = Hero("泰達米爾", "旋風斬", 2600, 450, 200)
gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400)
# 直接輸出對象即爲地址
print(gailun)
# <__main__.Hero object at 0x0318B100>
print(taidamier)
# <__main__.Hero object at 0x0318B0D0>
# 不同對象的屬性值的單獨保存
print(id(taidamier.name))
print(id(gailun.name))
# 同一個類的不同對象,實例方法共享
print(id(taidamier.move()))
# 泰達米爾 正在前往事發地點...
# 2045877480
print(id(gailun.move()))
# 蓋倫 正在前往事發地點...
# 2045877480
輸出結果
<__main__.Hero object at 0x0318B100>
<__main__.Hero object at 0x0318B0D0>
51928864
51928912
泰達米爾 正在前往事發地點...
2045877480
蓋倫 正在前往事發地點...
2045877480
如果是屬性則直接輸出其地址值,如果是方法則先執行方法在輸出地址值
- 通過一個類,可以創建多個對象,就好比通過一個模具創建多個實體一樣
- init(self)中,默認有1個參數名字爲self,如果在創建對象時傳遞了2個實參,那麼__init__(self)中出了self作爲第一個形參外還需要2個形參,例如__init__(self,x,y)
- 注意:
- ①在類內部獲取 屬性 和 實例方法,通過self獲取;
- ②在類外部獲取 屬性 和 實例方法,通過對象名獲取。
- ③如果一個類有多個對象,
每個對象的屬性是各自保存的,都有各自獨立的地址
; - ④
但是實例方法是所有對象共享的,只佔用一份內存空間
。類會通過self來判斷是哪個對象調用了實例方法。
七.魔法方法__str__()
- 當使用print輸出對象的時候,默認打印對象的內存地址。如果類定義了__str__(self)方法,那麼就會打印從在這個方法中 return 的數據
class Hero(object):
"""定義了一個英雄類,可以移動和攻擊"""
def __init__(self, name, skill, hp, atk, armor):
""" __init__() 方法,用來做變量初始化 或 賦值 操作"""
# 英雄名
self.name = name # 實例變量
# 技能
self.skill = skill
# 生命值:
self.hp = hp # 實例變量
# 攻擊力
self.atk = atk
# 護甲值
self.armor = armor
def move(self):
"""實例方法"""
print("%s 正在前往事發地點..." % self.name)
def attack(self):
"""實例方法"""
print("發出了一招強力的%s..." % self.skill)
# def info(self):
# print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
# print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
# print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))
def __str__(self):
"""
這個方法是一個魔法方法 (Magic Method) ,用來顯示信息
該方法需要 return 一個數據,並且只有self一個參數,當在類的外部 print(對象) 則打印這個數據
"""
return "英雄 <%s> 數據: 生命值 %d, 攻擊力 %d, 護甲值 %d" % (self.name, self.hp, self.atk, self.armor)
taidamier = Hero("泰達米爾", "旋風斬", 2600, 450, 200)
gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400)
# 如果沒有__str__ 則默認打印 對象在內存的地址。
# 當類的實例化對象 擁有 __str__ 方法後,那麼打印對象則打印 __str__ 的返回值。
print(taidamier)
print(gailun)
# 查看類的文檔說明,也就是類的註釋
print(Hero.__doc__)
英雄 <泰達米爾> 數據: 生命值 2600, 攻擊力 450, 護甲值 200
英雄 <蓋倫> 數據: 生命值 4200, 攻擊力 260, 護甲值 400
定義了一個英雄類,可以移動和攻擊
- ①在python中方法名如果是
__xxxx__()
的,那麼就有特殊的功能,因此叫做“魔法”方法
- ②__str__方法通常返回一個字符串,作爲這個對象的描述信息
八.魔法方法__del__()
- 創建對象後,python解釋器默認調用__init__()方法;
- 當刪除對象時,python解釋器也會默認調用一個方法,這個方法爲__del__()方法
class Hero(object):
# 初始化方法
# 創建完對象後會自動被調用
def __init__(self, name):
print('__init__方法被調用')
self.name = name
# 當對象被刪除時,會自動被調用
def __del__(self):
print("__del__方法被調用")
print("%s 被 GM 幹掉了..." % self.name)
# 創建對象
taidamier = Hero("泰達米爾")
# 刪除對象
print("%d 被刪除1次" % id(taidamier))
del(taidamier)
print("--" * 10)
gailun = Hero("蓋倫")
gailun1 = gailun
gailun2 = gailun
print("%d 被刪除1次" % id(gailun))
del(gailun)
print("%d 被刪除1次" % id(gailun1))
del(gailun1)
print("%d 被刪除1次" % id(gailun2))
del(gailun2)
運行結果
__init__方法被調用
54112464 被刪除1次
__del__方法被調用
泰達米爾 被 GM 幹掉了...
--------------------
__init__方法被調用
54112464 被刪除1次
54112464 被刪除1次
__del__方法被調用
蓋倫 被 GM 幹掉了...
- 當有變量保存了一個對象的引用時,此對象的引用計數就會加1;
- 當使用del() 刪除變量指向的對象時,則會減少對象的引用計數。如果對象的引用計數不爲1,那麼會讓這個對象的引用計數減1,當對象的引用計數爲0的時候,則對象纔會被真正刪除(內存被回收)。
The best investment is in yourself
2020.04.03 記錄辰兮的第46篇博客