Day 14 物件與類別:我們不一樣,每個人都有不同的際遇(下)
註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。
https://ithelp.ithome.com.tw/articles/10244886/
前面兩篇我們從什麼是類別和物件的基本介紹起,
講到如何初始化及設定屬性、方法,以及如何運用繼承。
這篇我們首先要談的是,
什麼時候該用類別/物件,什麼時候又該用模組呢?
其實答案很簡單:
看怎麼用比較方便,就怎麼用XD!
讀者可能會覺得這是廢話,先別著急,讓筆者解釋一下。
在程式的世界裡,當我們遇上問題時,
大部分的狀況下都不會只有一種解法 。
不同的解法,會有不同的優劣性,
扣除掉一些根本效率的不同,剩下的就只是取捨問題。
所以當碰到多個可行的選項,在考慮用哪一個方法時,
請先問問自己以下的問題:
- 題目(或現實的目標)是否有限制,導致某些方法其實不能用?
- 這當中,哪些是前面寫起來比較簡單,後面維護(或擴充)比較麻煩的?
哪些是前面寫起來比較複雜,後面卻可以節省力氣的? - 承2,在大前提的目標下,這個架構有需要考慮到後面的問題嗎?
以上三個問題會影響實務上的選擇,
所以你可以基於節省空間考量而選方法A,
或基於節省時間而選方法B,亦或是為了架構比較好選方法C,
不會有絕對的對錯,只是看考量而已。
扯遠了,回過頭來看物件/類別及模組的抉擇。
通常模組會比物件/類別還要精簡,因為不會牽扯到太多額外的東西;
但模組在一個程式中import時,只會產生同一個東西,而類別可以產生多個不同的物件。
當你的程式都是一些工具型函式,屬於那種呼叫完就會經過一番處理再輸出,
但不會需要產生多個不同的物件來處理事情的話,
以模組的型式處理會相當簡單。
舉例來說,一個學校只會有一個校長,校長可能有一些事情是他的權責範圍,
假設我們只鎖定一間學校,那校長能做的事情應該就可以直接以一個模組來囊括,
因為同一間學校總不會出現第二位校長嘛!所以我們可以用模組來定義所有校長的業務。
但學生就不行了,我們會有阿明,小美,HowHow跟其他路人甲乙丙丁,
所以學生就適合建立一個Student的類別來生成多個物件。
另一點是阿明和小美雖然都是學生,但它們會有屬性的差異,
這種有相同性質但屬性質不同的,最適合使用類別與物件來處理了!
另一方面,模組是不行繼承的 ,如果你有繼承的需求的話,
類別與物件就是唯一的選擇。
最後一點,如果可以用簡單的方式如字典、串列甚至一般函式來處理的話,
不一定非得要模組或類別/物件不可 。
接著我們來談談類別方法 及類別屬性 。
類別方法是指會影響整個類別的方法,類別屬性則是指整個類別所共有的屬性。
舉例來說,如果我們想要知道今天我們總共加入了幾個Student類別的物件,
我們可以這麼寫:
| |
| |
| |
| |
| |
結果應該像這樣:
| |
對於類別方法,我們會在前面加上**”@classmethod”,
同時由於”class”** 已經是Python的保留字(用來定義類別),
所以在使用時Python是給定**”cls”** ,用來指稱這個類別。
不過直接使用**Student.cnt**也可以,意思是一樣的。
所以請留意類別方法/屬性和物件方法/屬性的差異,
前者是屬於整個類別,後者是會依照產生的物件來操作。
可以看到即便在開始之前,
我們還沒加入任何Student,類別屬性就已經存在了。
還有一種比較特別的方法叫靜態方法 。
使用”@staticmethod”來開頭,不需要self或cls參數,
通常用以處理可以固定不變,不受其他屬性影響的東西。
例如:
| |
| |
同樣,無須Desolve類別產生物件,這個方法就能被使用(甚至也沒有用到其他屬性)。
一個類別也可以繼承不只一個類別,例如假設我們有A, B兩個類別,
想用一個C類別同時繼承它們:
| |
這麼一來,C就會同時擁有A跟B的屬性和方法。
那麼,如果相衝突(比方說重名)怎麼辦?
| |
| |
| |
輸出應該會如下:
| |
簡單來說,當A跟B有相同的方法時,
呼叫方法會呼叫哪一個,端看你把誰寫前面,寫越前面的優先程度越大 。
(讀者可以自行將C(A, B)改成C(B, A)看看結果)
其他還有一些更深入的變化,我們就不在這個系列討論了,
有興趣的讀者可以再深入研究繼承多個類別的變化。
最後,我們來談談特殊的方法:
當我們在Python內使用那些 ==, !=, >=, <=, >, <……等比較運算子時,
其實是依靠Python有對這些東西做定義,才知道如何去做比較;
但是對於我們自己生成的類別來說,想要比較兩個相同類別的物件,
可能就需要我們自己定義了。
例如說假設有一個類別叫nmod3(),會紀錄數字並判斷餘數是否相等:
| |
| |
可以被特別定義的除了比較運算子以外,還有之前我們提到過的算術運算子等。
這裡稍微列出一些提供參考:
| |
那我們一樣來練習一下題目吧!
- 請參照之前的Student類別,
假設今天有一個科系要求是(數學 * 2 + 英文 * 5)的加權分數採計,
定義__gt__(也就是>), __eq__(也就是==),
用上面的採計方式及重新定義的比較運算子來寫成新的A.compareE(B)函式,
假設:
A的加權分高於B -> A的名字 + ‘ > ‘ + B的名字
A的加權分等於B -> A的名字 + ‘ == ‘ + B的名字
A的加權分小於B -> A的名字 + ‘ < ‘ + B的名字
並分別讓阿明和HowHow比較、
阿明和小美比較、小美和HowHow比較,輸出結果。
(請保留之前compare的函式及呼叫的比較,我們兩種都要比呦!) - 承上,請使用類別方法和屬性,在每次進行比較時就將總比較次數+1,
並print出來,這邊的「比較」是指compare()及compareE()都算。
辛苦啦!那我們就明天見囉!
工商時間:
抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
在Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」
超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!
期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)
容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享 ,及訪談國內外不同經驗的工程師 ,
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作 ,
是初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」 :
https://bit.ly/advleetcode
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/allleetcode
