前言
對於萌新來說,面向對象,這是一個很陌生的詞語。如果你接觸過Linux,你一定知道“一切皆文件”,也就是說,在Linux中所有都是文件,鼠標是文件、鍵盤是文件、目錄是文件等等一切都是文件;Python設計時就是一門面向對象的語言,在Python中,秉承“一切皆對象”,也就是說,在Python中見到的一切都是對象。面向對象是一個很抽象的概念,來一點一點剖析它!
一、程序編程典范
在編程中,想要實現同樣的功能,可能會有好多種編寫方法,畢竟條條大路通羅馬,隨着編寫方法的不斷聚類,出現了三種主要的程序編程典范,分別是:面向過程編程、函數式編程、面向對象編程。這三種編程典范各有千秋,比較一下便知。
1.1 面向過程編程
面向過程編程的思想是讓程序從頭到尾一步步執行,環環相扣。對於小程序和小腳本來說,面向過程是最方便的。但是面向過程也有這致命的缺點,代碼的重復利用率極低,假如程序中有十次需要拿到列表里數字元素的最小值,那就要重復編寫十次這個代碼,很煩對不對,突然需求變了,不要最小值了,要最大值,那就要更改程序十次,更煩😡
1 list1 = [1, 2, 3, 4, 5, 6, 7] 2 list2 = [2, 3, 1, 5, 5, 3, 1] 3 list3 = [23, 456, 134, 45] 4 5 max_num = list1[0] 6 for i in list1: 7 if max_num < i: 8 ¦ max_num = i 9 print(max_num) 10 11 12 max_num = list2[0] 13 for i in list2: 14 if max_num < i: 15 ¦ max_num = i 16 print(max_num) 17 18 19 max_num = list3[0] 20 for i in list3: 21 if max_num < i: 22 ¦ max_num = i 23 print(max_num) 24 25 # 可以看到每次都要寫一遍代碼,重復利用率極低
1.2 函數式編程
於是函數便應運而生了,函數的出現大大增加了代碼的重復利用率,並且修改起來也特別方便,程序也容易擴展。將上面的需求編寫為一個函數即可,每次使用時調用函數即可,當需求變了以后,直接修改函數的代碼塊就可以解決。這就是函數式編程,聽起來超級方便是不是,以上就是函數式編程的優點。
1 def maxNum(nums): 2 ''' 3 返回nums中的最大數字 4 ''' 5 max_num = nums[0] 6 for i in nums: 7 ¦ if max_num < i: 8 ¦ ¦ max_num = i 9 print(max_num) 10 11 12 list1 = [1, 2, 3, 4, 5, 6, 7] 13 list2 = [2, 3, 1, 5, 5, 3, 1] 14 list3 = [23, 456, 134, 45] 15 16 maxNum(list1) 17 maxNum(list2) 18 maxNum(list3) 19 20 21 # 使用函數極大的提高了代碼的重復利用率
1.3 面向對象編程
但但但但但是,函數式編程就沒有缺點了嗎?當然有,要不然就不會出現面向對象編程了。
假如現在有三個角色,分別是張三、李四、王二麻子,他們的職業分別是老師、醫生、建造師,需要實現的功能是吃飯、說話、教書、治療、建造。按照函數式編程的思想,這些功能就是函數嘛,搞起:
1 def eat(name): 2 pass 3 def talk(name): 4 pass 5 def teach(name): 6 pass 7 def treat(name): 8 pass 9 def build(name): 10 pass 11 12 # 三個人都能吃 13 eat('張三') 14 eat('李四') 15 eat('王二麻子') 16 17 # 三個人都能說話 18 talk('張三') 19 talk('李四') 20 talk('王二麻子') 21 22 # 只有張三可以教書 23 teach('張三') 24 25 # 只有李四可以治療 26 treat('李四') 27 28 # 只有王二麻子可以建造 29 build('王二麻子')
上面的代碼看起來實現了要有的功能,但是有一個致命的問題,那就是張三好像也可以治療和建造、李四也可以教書和建造、王二麻子也可以教書和治療,無非不過傳遞參數的時候換一個人名,這明顯是不允許的!要是可以做出限制就好了,教師只能去教書,不能去治療和建造,這就是面向對象編程的思想。
二、面向對象簡介
從上圖可以看出,對象來自於類,對象能干的事只有類里的方法,現在又稀里糊塗多了一個更加陌生的新名詞:類
2.1 面向對象核心
類(class):用來描述屬性和方法的集合。
方法:類中定義的函數
對象:類的實例化
「解釋」面向對象編程就是物以類聚,人以群分。有一個職業叫做醫生(類),這是一個抽象的存在;李四(對象)是一個醫生,這是一個具體而真實的存在;因為醫生(類)可以吃飯、說話、治療,不可以教書,那么張三(對象)就可以吃飯、說話、治療,不可以教書。
這就是面向對象編程,尤其對於游戲開發及其重要,比如英雄聯盟,所有英雄都可以使用召喚師技能(點燃、閃現等),不同英雄又有着各自不同的技能
2.2 一切皆對象
Python在設計之初就是一門面向對象編程語言,特點就是:一切皆對象。字符串、列表、字典等這些都是類,每當你創建一個具體的字符串,就相當於類的實例化對象,這個具體的對象就可以使用字符串類里的方法,這也就是為什么不同數據類型擁有不同的方法
In [2]: print(type('')) <class 'str'> In [3]: print(type([])) <class 'list'> In [4]: print(type({})) <class 'dict'> In [5]: print(type(())) <class 'tuple'> # 可以看到這些數據類型都是類
三、類的創建和實例化
3.1 基本語法
「創建」說了這么多,相信你已經明白了面向對象編程的思想。那么接下來就要開始創建類了。基本語法如下:
class 類名: ''' 類的幫助信息 ''' 類的代碼塊(可以是語句、函數、類)
可以看到類的定義和函數的定義差不多,舉幾個例子吧:
class Doctor: ''' 創建一個醫生類 ''' def eat(self): ¦ print('我喜歡吃') def talk(self): ¦ print('我喜歡說話') def treat(self): ¦ print('我喜歡治療病人') class Teacher: ''' 創建一個老師類 ''' def eat(self): ¦ print('我喜歡吃') def talk(self): ¦ print('我喜歡說話') ¦ def teach(self): ¦ print('我喜歡教書')
「實例化」類的實例化其實很簡單,只需要 對象 = 類() 即可,舉例子:
zhangsan = Teacher() # 將Teacher類實例化為對象張三 lisi = Doctor() # 將Doctor類實例化為對象李四
「屬性訪問」使用 實例化對象.方法() 即可,例如:
zhangsan.eat()
zhangsan.teach()
lisi.talk()
lisi.treat()
# 運行結果 我喜歡吃 我喜歡教書 我喜歡說話 我喜歡治療病人
3.2 self參數
細心的小伙伴已經發現類里的每一個函數都有一個默認參數self,這個self是什么呢?我們先來打印一下看看:
class Teacher: def eat(self): ¦ print(self) # 打印self lisi = Teacher() lisi.eat() # 運行結果 <__main__.Teacher object at 0x1014b12e8>
可以看到self是Teacher object,object的中文意思為對象,也就是說,self是類的實例化對象,也就是lisi。
類中函數的第一個參數是固定表示對象的,與叫什么無關,self是大家約定俗成的叫法而已,換成其他名稱也是可以的,比如換成sb
class Teacher: def eat(sb): ¦ print(sb) lisi = Teacher() lisi.eat() # 運行結果: <__main__.Teacher object at 0x104034320>
不是特殊需要盡量不要改變self的名稱啦🐷
小結
關於面向對象第一小節就記錄這么多,主要是理解面向對象的思想以及簡單類的創建。之后會講解類的各種變量、類的傳參、類的性質、類的各種方法。今天就肝到這里