Python面向對象編程——簡介
編程范式
編程是程序員用特定的
語法+數據結構+算法
組成的代碼來告訴計算機如何執行任務的過程 。
一個程序是程序員為了得到一個任務結果而編寫的一組指令的集合,正所謂條條大路通羅馬,實現一個任務的方式有很多種不同的方式, 對這些不同的編程方式的特點進行歸納總結得出來的編程方式類別,即為編程范式。 不同的編程范式本質上代表對各種類型的任務采取的不同的解決問題的思路, 大多數語言只支持一種編程范式,當然也有些語言可以同時支持多種編程范式。 兩種最重要的編程范式分別是面向過程編程和面向對象編程。
一、面向過程編程(Procedural Programming)
Procedural programming uses a list of instructions to tell the computer what to do step-by-step.
面向過程編程依賴 - 你猜到了- procedures,一個procedure包含一組要被進行計算的步驟, 面向過程又被稱為top-down languages, 就是程序從上到下一步步執行,一步步從上到下,從頭到尾的解決問題 。基本設計思路就是程序一開始是要著手解決一個大的問題,然后把一個大問題分解成很多個小問題或子過程,這些子過程再執行的過程再繼續分解直到小問題足夠簡單到可以在一個小步驟范圍內解決。
舉個典型的面向過程的例子, 寫一個數據遠程備份程序, 分三步,本地數據打包,上傳至云服務器,測試備份文件可用性。
def cloud_upload(file):
print("\nconnecting cloud storage center...")
print("cloud storage connected.")
print("upload file...xxx..to cloud...", file)
print('close connection.....')
def data_backup(folder):
print("找到要備份的目錄...", folder)
print("將備份文件打包,移至相應目錄...")
return '/tmp/backup20181103.zip'
def data_backup_test():
print("\n從另外一臺機器將備份文件從遠程cloud center下載,看文件是否無損")
def main():
zip_file = data_backup("c:\\users\\alex\歐美100G高清無碼")
cloud_upload(zip_file)
data_backup_test()
if __name__ == '__main__':
main()
這個變量,那這個子過程你也要修改,假如又有一個其它子程序依賴這個子過程 , 那就會發生一連串的影響,隨著程序越來越大, 這種編程方式的維護難度會越來越高。
test = 1
def cloud_upload(file):
if test == 1:
print("\nconnecting cloud storage center...")
print("cloud storage connected.")
print("upload file...xxx..to cloud...", file)
print('close connection.....')
return True
else:
print("不備份")
return False
def data_backup(folder):
print("找到要備份的目錄...", folder)
print("將備份文件打包,移至相應目錄...")
return '/tmp/backup20181103.zip'
def data_backup_test(upload_res):
if upload_res == 1:
print("\n從另外一臺機器將備份文件從遠程cloud center下載,看文件是否無損")
else:
print("upload error,不備份")
def main():
zip_file = data_backup("c:\\users\\alex\歐美100G高清無碼")
res = cloud_upload(zip_file)
data_backup_test(res)
if __name__ == '__main__':
main()
所以我們一般認為, 如果你只是寫一些簡單的腳本,去做一些一次性任務,用面向過程的方式是極好的,但如果你要處理的任務是復雜的,且需要不斷迭代和維護 的, 那還是用面向對象最方便了。
二、面向對象編程(Object Oriented Programing)
直接解釋,你必然會蒙逼,所以先講個引子。
你現在是一家游戲公司的開發人員,現在需要你開發一款叫做 的游戲,你就思考呀,人狗作戰,那至少需要2個角色,一個是人, 一個是狗,且人和狗都有不同的技能,比如人拿棍打狗, 狗可以咬人,怎么描述這種不同的角色和他們的功能呢?
你搜羅了自己掌握的所有技能,寫出了下面的代碼來描述這兩個角色:
person = {
'name':'Alex',
'attack': 100, #殺傷力
'life_value':1000
}
dog = {
'name':'Peiqi',
'attack': 200, #殺傷力
'life_value':800
}
一個字典表示一個角色實體,但如果有多條狗和多個人一起打呢?那就得寫多個字典。
person = {
'name':'Alex',
'attack': 100, #殺傷力
'life_value':1000
}
person2 = {
'name':'Black Girl',
'attack': 100, #殺傷力
'life_value':600
}
dog = {
'name':'Peiqi',
'attack': 200, #殺傷力
'life_value':800
}
這樣是有問題的,因為如果你字典里的值不小心定義錯了,把attack寫成了了atteck的話,那整個程序就有問題了。so 你很快想出了改進方案,把字典放進函數
def person(name,attack,life_value):
data = {
'name':name,
'attack':attack,
'life_value':life_value,
}
return data
def dog(name, attack, life_value):
data = {
'name': name,
'attack': attack,
'life_value': life_value,
}
return data
alex = person("Alex",100,1000)
rain = person("Black girl",80,700)
d = dog("PeiQi",200,800)
好,現在角色定義好了,還差每個角色的功能,人打狗,狗咬人的功能要定義出來
....
def attack(p,d):
"""人打狗功能"""
d['life_value'] -= p['attack'] #被打了,要掉血
print("人[%s] 打了 狗[%s]。。。,[%s]的生命值還有[%s]" % (p['name'], d['name'],d['name'],d['life_value']))
def bite(d,p):
"""狗咬人功能"""
p['life_value'] -= d['attack']
print("狗[%s] 咬了 人[%s]。。。,[%s]的生命值還有[%s]" % (d['name'], p['name'],p['name'],p['life_value']))
alex = person("Alex",100,1000)
black_girl = person("Black girl",80,700)
d = dog("PeiQi",200,800)
attack(alex,d)
bite(d,black_girl)
現在,就可以開心的玩耍啦。。。
但玩著玩著, 你不小心調用錯了,
bite(alex,black_girl) #你調用咬人功能時,把alex當狗傳進去了,結果就變成了如下
人[Alex] 打了 狗[PeiQi]。。。,[PeiQi]的生命值還有[700]
狗[PeiQi] 咬了 人[Black girl]。。。,[Black girl]的生命值還有[500]
狗[Alex] 咬了 人[Black girl]。。。,[Black girl]的生命值還有[400]
你讓我咬black_girl一口我不介意,但以狗的身份,我是反對的,所以這明顯是個bug,bite()功能是狗專屬的,不應該允許人調用,這可怎么辦呢?
哈,想了一會,你又搞定了。
def person(name,attack_val,life_value):
def attack( d):
"""人打狗功能"""
d['life_value'] -= attack_val # 被打了,要掉血
print("人[%s] 打了 狗[%s]。。。,[%s]的生命值還有[%s]" % (name, d['name'], d['name'], d['life_value']))
data = {
'name':name,
'attack_val':attack_val,
'life_value':life_value,
'attack':attack
}
return data
def dog(name, attack_val, life_value):
def bite(p):
"""狗咬人功能"""
p['life_value'] -= attack_val
print("狗[%s] 咬了 人[%s]。。。,[%s]的生命值還有[%s]" % (name, p['name'], p['name'], p['life_value']))
data = {
'name': name,
'attack_val': attack_val,
'life_value': life_value,
'bite':bite
}
return data
alex = person("Alex",100,1000)
black_girl = person("Black girl",80,700)
d = dog("PeiQi",200,800)
alex['attack'](d)
d['bite'](black_girl)
你是如此的機智,這樣就實現了限制人只能用人自己的功能啦。
但,我的哥,不要高興太早,剛才你只是阻止了兩個完全 不同的角色 之間的功能混用, 但有沒有可能 ,同一個種角色,但有些屬性是不同的呢? 比如 ,現在游戲升級了,不僅可以打狗,還可以生孩子,但男人不能生呀,只能女的生,怎么辦呢?你想了想說,簡單呀, 在person函數里包一個子函數叫
get_birth(),
def get_birth(person_data):
if person_data['sex'] == 'female':
print("%s生孩子 啦..."% person_data['name'] )
else:
print("你是男的生個毛線.")
沒錯, 這雖然解決了只能女人生孩子的問題,但其實隨著游戲功能越來越多,你會發出男女之間的區別也越來越多 ,但又同時有很多共性,如果 在每個區別處都 單獨做判斷,那得累死。
你想了想說, 那就直接寫2個角色吧, 反正 這么多區別, 我的哥, 不能寫兩個角色呀,因為他們還有很多共性 , 寫兩個不同的角色,就代表 相同的功能 也要重寫了,是不是我的哥? 。。。 沒話說了吧?哈哈, 就是要逼你到絕路上。
上面的問題通過面向對象編程可輕松解決!
什么是面向對象編程?
OOP(Object Oriented Programing)編程是利用“類”和“對象”來創建各種模型來實現對真實世界的描述。
上面的描述你必定是懵逼的,用白話解釋面向對象與面向過程的區別就是:
面向過程 = 個人視角
我要去做大保健,我只需考慮,我有沒有錢,去哪家店,怎么去,做什么價位的就可以,你的每一步都要通過程序定義出來,寫死了,在這個程序里,你只被設定了去做大保健的功能,你說中途我想去個ktv,那可能會導致整個程序的邏輯都得更改。 用面向過程的方式寫代碼,那你care的就是整個事情的執行過程
面向對象 = 上帝視角
如果你是上帝,你現在要創世紀,把這么多人、動物、山河造出來,上帝光靠自己干,一個一個的造人,多累呀,讓你干這個活,你肯定是先造模子,一個男人模子,一個女人模子,剩下的就一個個復制就行啦。這個模子的作用是什么?模子定義了人這個物種所具備的所有特征(或者說,我們把具備這些特征的個體歸為人類)。
這個世界上所有的東西都是你定義的,你需要用最高效的方式去造世界,最高效的方式就是,先把世界按物種、樣貌、有無生命等各種維度分類,然后給每類東西建模型,再讓其在不脫離你基本橫型定義的框架下,自我繁衍(世界要多姿多彩,所以即使是同一物種,也要有些不一樣)
為什么要用面向對象?
1、使程序更加容易擴展和易更改,使開發效率變的更高。
2、基于面向對象的程序可以使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。
三、面向對象介紹
學習面向對象過程中會遇到一些名詞,我們先解釋下:
名詞解釋
類 :一個類即是一類擁有相同屬性的對象的抽象、藍圖、原型、模板。在類中定義了這些對象都具備的屬性(variables(data))、共同的方法。
屬性 :人類包含很多特征,這些特征用程序來描述的話,叫做屬性,比如年齡、身高、性別、姓名等都叫做屬性,一個類中,可以有多個屬性。
方法 :人類不止有身高、年齡、性別這些屬性,還能做很多事情,比如說話、走路、吃飯等,相比較于屬性是名詞,說話、走路是動詞,這些動詞用程序來描述就叫做方法。
實例(對象) :一個對象即是一個類實例化后的實例,一類必須經過實例化之后才可在程序中調用,一個類可以實例化多個對象,每個對象亦可以有不同的屬性,就像人類是指所有人,每個人是指具體的對象,人與人之間有共性,亦有不同。
實例化 :把一個類轉變為一個對象的過程就叫實例化。
面向對象的3大特性
Encapsulation 封裝
在類中對數據的賦值、內部調用對外部用戶是透明的,這使類變成了一個膠囊或容器,里面包含著類的數據和方法。
Inheritance 繼承
一個類可以派生出子類,在這個父類里定義的屬性、方法自動被子類繼承。
Polymorphism 多態
多態是面向對象的重要特性,簡單點說:“一個接口,多種實現”,指一個基類中派生出了不同的子類,且每個子類在繼承了同樣的方法名的同時又對父類的方法做了不同的實現,這就是同一種事物表現出的多種形態。
編程其實就是一個將具體世界進行抽象化的過程,多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再通過這個抽象的事物, 與不同的具體事物進行對話。
對不同類的對象發出相同的消息將會有不同的行為。比如,你的老板讓所有員工在九點鐘開始工作, 他只要在九點鐘的時候說:“開始工作”即可,而不需要對銷售人員說:“開始銷售工作”,對技術人員說:“開始技術工作”, 因為“員工”是一個抽象的事物, 只要是員工就可以開始工作,他知道這一點就行了。至于每個員工,當然會各司其職,做各自的工作。
多態允許將子類的對象當作父類的對象使用,某父類型的引用指向其子類型的對象,調用的方法是該子類型的方法。這里引用和調用方法的代碼編譯前就已經決定了,而引用所指向的對象可以在運行期間動態綁定。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
