1. 程式人生 > >python D14 面向物件

python D14 面向物件

# 本節主要內容:
# 1、面向物件
# 2、面向物件如何編寫
# 3、面向物件和麵向過程大pk
# 4、面向物件三大特徵

# 一、面向物件和麵向過程
# 1. ⾯向過程: ⼀切以事物的流程為核⼼. 核⼼是"過程"⼆字, 過程是指解決問題的步驟,
# 即, 先⼲什麼, 後⼲什麼. 基於該思想編寫程式就好比在編寫⼀套流⽔線. 是⼀種機械
# 式的程式設計思維
# 面向過程:站在自己的角度先做什麼後做什麼,主要在過程上面
# 優點: 負責的問題流程化, 編寫相對簡單
# 缺點: 可擴充套件性差

# 2. ⾯向物件: ⼀切以物件為中⼼.
# 什麼是物件? 不好解釋. 先解釋解釋什麼是⻋? 有軲轆, 有⽅向盤, 有發動機, 會跑的
# 是⻋. 好. 在解釋⼀個. 什麼是⼈. 有名字, 年齡, 愛好, 會唱歌跳舞思考的是⼈. 我們給這兩個
# 東⻄下了⼀個簡單的定義. 總結: 具有相同屬性和動作的結合體叫物件. ⾯向物件思維, 要⾃
# ⼰建立物件. ⾃⼰建立場景. 你是就是⾯向物件世界中的上帝. 你想讓⻋⼲嘛就⼲嘛. 你想讓
# ⼈⼲嘛⼈就能⼲嘛.
# 面向物件:站在上帝視角,以物件為中心,命令物件去做什麼
# 優點: 可擴充套件性強
# 缺點: 程式設計的複雜度⾼於⾯向過程

# 對比:
# 說. 要把⼤象裝冰箱, 總共分⼏步? 三步. 第⼀步. 開啟冰箱⻔, 第⼆部. 裝⼤象, 第三
# 部. 關冰箱⻔. 這是⼀個典型的⾯向過程的思維⽅式. 來我們如果換成⾯向物件呢? 很簡單. 想
# 辦法造⼀個會鑽冰箱的⼤象就可以了. 然後命令⼤象. 進冰箱. ⼤象就乖乖的進冰箱了. 這就
# 是⾯向物件思維. 我們⾯向的不再是事物發展的流程, ⽽是操縱某⼀個事物的個體. 具體的某
# ⼀個事物.

# 二、面向物件如何編寫
# 說了這麼多. ⾯向物件的程式如何編寫呢? 想想在我們的世界中. 我們如何造⼀輛⻋?
# 先由設計師來設計圖紙. 設計師在圖紙上勾勒出⻋應該是xx樣的. 應該有什麼. 以及這臺⻋的
# 功能等等. 然後交給⼯⼚進⾏代⼯. 根據設計師設計的圖紙去創造⻋. 程式也⼀樣. 我們需要
# 先設計⼀個圖紙. 在圖紙上把我要建立的物件進⾏描述. 然後交給⼯⼈去建立物件.
# 在這⾥, 我們畫圖紙的過程需要我們寫類, 我們⽤類來描述⼀個物件. 類的語法很簡單
# class girlfriend: # 這裡就建立了一個類
# pass
# gf = girlfriend() # 這裡就建立了一個物件
# gf.foot = "大長腿" # 物件的屬性
# gf.eyes = '大眼睛'
# gf.hair = '烏黑大長髮'
# gf.bosom = '35D'
# gf.type = "sexy"
# 接下來, 再造⼀gf, 並給gf設定相關的屬性資訊
# gf2 = girlfriend()
# gf2.foot = "大長長腿"
# gf2.eyes = '大眼睛'
# gf2.hair = '烏黑大長髮'
# gf2.bosom = '36D'
# gf2.type = "chubby"
# print(gf2.type)

# 我們發現, 這兩量gf是完全不同的兩量gf. 但是. 擁有相同的屬性和資訊. 是不是有點⼉
# 冗餘了? 怎麼辦呢? 想想. 我們把⻋的資訊如果寫在類⾥是不是會更好呢? ⽽且. 我的girkfirend在創
# 建的時候這些資訊應該已經是設計好了的. 不應該是後天設計的. 好了, 我們知道需求了, 在
# 建立物件的時候能給物件設定⼀些初始化的屬性資訊. 在python中我們可以是⽤__init__(self)
# 函式給物件進⾏初始化操作. 這個函式(⽅法)被稱為建構函式(⽅法).
# class girlfirend:
# def __init__(self, foot, eyes, hair, bosom, type):
# self.foot = foot
# self.eyes = eyes
# self.hair = hair
# self.bosom = bosom
# self.type = type
# gf1 = girlfirend("大長腿", "大眼睛", "烏黑大長髮", "35D", "sexy", )
# print(gf1.type) # sexy
# gf2 = girlfirend("大大長腿", "大大眼睛", "長髮", "36D", "sexy", )
# print(gf2.eyes) # 大大眼睛
# 通過列印, 我們發現.這兩個物件依然像原來那樣可以完成屬性的設定.

# 屬性設定完了. 接下來. ⻋不光有這些資訊啊. ⻋還會跑呢. 跑是⼀個動作. 所以我們要
# 把跑寫成⼀個函式. 但是在⾯向物件程式設計中. 我們不應該叫函數了, 改成叫⽅法. 只不過這個
# ⽅法寫起來比正常的⽅法多⼀個引數self. 僅此⽽已
# class Car:
# def __init__(self, color, pai, pailiang): # self表示當前類的物件. 當前你建立的是誰, 誰來訪問的這個⽅法.那這個self就是誰.
# self.color = color
# self.pai = pai
# self.pailiang = pailiang
# def run(self, speed):
# print("⻋可以跑%s邁" % speed)
# c = Car("red", "京A66666", "2.0T")
# c.run(100) # ⻋可以跑100邁 這時. python會⾃動把物件c傳遞給run⽅法的第⼀個引數位置.
# 總結: 類與物件的關係: 類是對事物的總結. 抽象的概念. 類⽤來描述物件. 物件是類的例項
# 化的結果. 物件能執⾏哪些⽅法. 都由類來決定. 類中定義了什麼. 物件就擁有什麼

# 練習:用面向物件思維拉完成使用者登入
# class uspas: # 建立一個登陸的類
# def __init__(self, username, password): # 定義這個類自帶的使用者名稱、密碼屬性
# self.username = username
# self.password = password
# def login(self, user, psw): # 定義登陸這個方法,使用者傳入賬號密碼
# if user == self.username and psw == self.password: # 驗證賬號密碼是否正確
# return "登陸成功"
# else:
# return "使用者名稱或密碼錯誤"
# usp = uspas("zhang", "hui123")
# ret = usp.login(user=input("請輸入你的賬號"), psw=input("請輸入你的密碼"))
# print(ret)

# 三. ⾯向物件和⾯向過程⼤PK
# 那麼⾯向物件和⾯向過程到底哪個好? 具體問題. 具體分析. 沒有絕對的好和不好. 這⼀點
# 要格外注意.
# 來. 我們來完成之前的裝⼤象的程式:
# 1、面向過程:
# 非函式版
# print("開啟冰箱門")
# print("裝大象")
# print("關冰箱門")
# # 函式版
# def open_d():
# print("開啟冰箱門")
# def zx():
# print("裝大象")
# def close_d():
# print("關冰箱門")
#
# # 2、面向物件:
# class El:
# def open(self):
# print("把門開啟")
# def zx(self):
# print("把自己裝進去")
# def close(self):
# print("關門")
# dx = El()
# dx.open()
# dx.zx()
# dx.close()
# 發現了吧, ⾯向物件簡直⿇煩到爆. 彆著急. 接著看下⼀個案例.
# ⼩豬佩奇⼤戰奧特曼. 說. 有⼀個⼩豬, 名叫佩奇, 今年40歲了. 會使⽤嘴巴嘟嘟必殺技. 他
# 不光⼤戰奧特曼, 還會⼤戰蝙蝠俠, 蜘蛛俠
# def da_ao_te_man(name, age, jn):
# print("%s, 今年%s歲了, 使⽤%s技能瘋狂輸出奧特曼" % (name, age, jn))
# def da_bian_fu_xia(name, age, jn):
# print("%s, 今年%s歲了, 使⽤%s技能瘋狂輸出蝙蝠俠" % (name, age, jn))
# def da_zhi_zhu_xia(name, age, jn):
# print("%s, 今年%s歲了, 使⽤%s技能瘋狂輸出蜘蛛俠" % (name, age, jn))
# da_ao_te_man("⼩豬佩奇", 39, "嘴巴嘟嘟")
# da_bian_fu_xia("⼩豬佩奇", 39, "嘴巴嘟嘟")
# da_zhi_zhu_xia("⼩豬佩奇", 39, "嘴巴嘟嘟")

# ⾯向物件
# class Pig:
# def __init__(self, name, age, jn):
# self.name = name
# self.age = age
# self.jn = jn
# def da_ao_te_man(self):
# print("%s, 今年%s歲了, 使⽤%s技能瘋狂輸出奧特曼" % (self.name, self.age,self.jn))
# def da_bian_fu_xia(self):
# print("%s, 今年%s歲了, 使⽤%s技能瘋狂輸出蝙蝠俠" % (self.name, self.age,self.jn))
# def da_zhi_zhu_xia(self):
# print("%s, 今年%s歲了, 使⽤%s技能瘋狂輸出蜘蛛俠" % (self.name, self.age,self.jn))
# peiqi = Pig("⼩豬佩奇", 39, "嘴巴嘟嘟")
# peiqi.da_ao_te_man()
# peiqi.da_bian_fu_xia()
# peiqi.da_zhi_zhu_xia()
# 感覺到⼀點⼉眉⽬了吧. 在這個案例中, 明顯⾯向物件的思想更加清晰⼀些. 程式碼也更容
# 易編寫⼀些. 所以. ⽤哪種程式設計思想不是絕對的. 得根據需求和需要來完成.

# 四. ⾯向物件的三⼤特徵
# ⾯向物件三⼤特徵: 封裝, 繼承, 多型. 只要是⾯向物件程式設計語⾔. 都有這三個特徵.
# 1. 封裝: 把很多資料封裝到⼀個物件中. 把固定功能的程式碼封裝到⼀個程式碼塊, 函式, 對
# 象, 打包成模組. 這都屬於封裝的思想. 具體的情況具體分析. 比如. 你寫了⼀個很⽜B
# 的函式. 那這個也可以被稱為封裝. 在⾯向物件思想中. 是把⼀些看似⽆關緊要的內容
# 組合到⼀起統⼀進⾏儲存和使⽤. 這就是封裝.
# 2. 繼承: ⼦類可以⾃動擁有⽗類中除了私有屬性外的其他所有內容. 說⽩了, ⼉⼦可以
# 隨便⽤爹的東⻄. 但是朋友們, ⼀定要認清楚⼀個事情. 必須先有爹, 後有⼉⼦. 順序不
# 能亂, 在python中實現繼承非常簡單. 在宣告類的時候, 在類名後⾯新增⼀個⼩括號,
# 就可以完成繼承關係. 那麼什麼情況可以使⽤繼承呢? 單純的從程式碼層⾯上來看. 兩
# 個類具有相同的功能或者特徵的時候. 可以採⽤繼承的形式. 提取⼀個⽗類, 這個⽗類
# 中編寫著兩個類相同的部分. 然後兩個類分別取繼承這個類就可以了. 這樣寫的好處
# 是我們可以避免寫很多重複的功能和程式碼. 如果從語義中去分析的話. 會簡單很多. 如
# 果語境中出現了x是⼀種y. 這時, y是⼀種泛化的概念. x比y更加具體. 那這時x就是y的
# ⼦類. 比如. 貓是⼀種動物. 貓繼承動物. 動物能動. 貓也能動. 這時貓在建立的時候就
# 有了動物的"動"這個屬性. 再比如, ⽩骨精是⼀個妖怪. 妖怪天⽣就有⼀個比較不好
# 的功能叫"吃⼈", ⽩骨精⼀出⽣就知道如何"吃⼈". 此時 ⽩骨精繼承妖精. 話不多說.
# 上程式碼.

# 在python中, ⼀個類可以同時繼承多個⽗類. 說⽩了, 現在⼀個⼉⼦可能會有多個爹了.
# 既然是有這麼多個爹, 總得有遠有近. 比如. 有⼀個這樣的⽜B的⼈物, 叫鍋不美. 就有很多個
# 爹嘛.
class QinDie:
def chi(self):
print("親爹給你好吃的")
def play(self):
print("親爹會陪你玩")

class GanDie:
def qian(self):
print("⼲爹給錢啊")
def play(self):
print("⼲爹會陪你玩")
class GuNiang(QinDie, GanDie):
pass
bumei = GuNiang()
bumei.chi() # 親爹
bumei.qian() # 親爹沒有, 找⼲爹
bumei.play() # 親爹有了, 就不找⼲爹了

# 3. 多型: 同⼀個物件, 多種形態. 這個在python中其實是很不容易說明⽩的. 因為我們⼀
# 直在⽤. 只是沒有具體的說. 比如. 我們建立⼀個變數a = 10 , 我們知道此時a是整數
# 型別. 但是我們可以通過程式讓a = "alex", 這時, a⼜變成了字串型別. 這是我們都
# 知道的. 但是, 我要告訴你的是. 這個就是多型性. 同⼀個變數a可以是多種形態. 可能
# 這樣的程式和說法你還get不到具體什麼是多型. 接下來. 我們來看⼀個程式. 北京動
# 物園飼養員alex⼀天的⼯作. 從早上開始餵養豬, 中午喂哈⼠奇, 晚上還得喂阿拉斯加.
# 來我們⽤程式碼實現這樣的程式碼:
class Animal:
def chi(self):
print("動物就知道吃")

class Pig:
def chi(self):
print("豬也在吃")

class Haski(Animal):
def chi(self):
print("哈⼠奇在吃")

class Alasika(Animal):
def chi(self):
print("阿拉斯加在吃")

class SiYangYuan:
def yanng_animal(self, ani):
ani.chi()

zhu = Pig()
erha = Haski()
ala = Alasika()
alex = SiYangYuan()
alex.yanng_animal(zhu) # 豬也在吃
alex.yanng_animal(erha) # 哈⼠奇在吃
alex.yanng_animal(ala) # 阿拉斯加在吃