Last Updated on 2021-04-07 by Clay
Python 當中的 Class 可說是設計模組最基礎的類別,也即是 Python 當中物件導向的寫法。
我們可以將想要產生的物件賦予一個 Class (類別),藉此大量複製某種特有的屬性。
將物件套用『類別』(Class) 可說是相當地方便,打個比方:今天我們想要製作一個『模擬市民』的遊戲(不知道大家有沒有玩過哈哈哈),每個人物都有著自己的『面板屬性』。
那麼,難道我們每創造一次人物都要重新建立該人物的屬性?
當然不是!我們可以設定存在著人物面板數性的 Class,在每次需要創造人物的時候,將人物賦予這個『人類』的 Class。
你或許會說,我們也可以使用 function 來完成啊?好比如將人物資料存成 Json 檔 (或許以後的章節我會提到關於 Python 當中 Json 的存取方式),每個人物都各自有著不同的屬性。
當然!我認為這也是一種方法!
不過 Class 有個比使用 function 建立屬性更方便的地方:繼承 Class,或者說是我們建立的 Class 具有擴展性。
假設我們今天要出資料片了(在這裡還是以模擬市民舉例),人物新增了警察、消防員...... 等等的職業。那麼,我們很有可能需要新增人物的屬性!比如說新職業的等級或專屬技能。
那麼,我們便可以新建一個專屬於 DLC 的類別,繼承原有的『人類』類別,並在這之上進行新職業的更新。
也許你還是會說:可是,修改我們原先建立的 function,並將人物資料新增在 Json 檔上,似乎還是一樣的效果啊?
別急,其實我還沒有說完啦!
如果今天在警察的對面有個新職業:『黑道』,那麼,我們可能會需要將類別括擴展出一些屬性,來專屬於這些可以跟主角互動的 NPC。
那麼,我們還是可以繼承『人類』這個 Class,再次建立屬於 NPC 的 Class。
而 function,很有可能就得寫成不同的 function,以此區分我們操控的角色的屬性、以及其他 NPC 的屬性。
當然,我承認 function 其實可以達到一樣的功能,只是在類別上可能有些不直覺。
說了那麼多,其實我認為真正要學會 class 要從實戰中體驗。學會了 class (類別),我認為,是學習 Python 一個重要的里程碑。
以下,便開始我們 Python 基本教學的最後一個筆記內容吧!
基礎 Class
以下,我們這次真的拿『人類』這個類別製作 Class。
class Human(): def __init__(self, name, age): self.name = name self.age = age if __name__ == '__main__': clay = Human('Clay', 25) print('Name:', clay.name) print('Age:', clay.age)
Output:
Name: Clay
Age: 25
"class" 這個指令後面接著我們要建立的 class 名稱,在這裡我建立了 Human 這個類別。
__init__ 為初始化的區塊。每當這個 class 作為物件被建立時,都會執行這底下的程式碼。可以看到,在第一次建立這個類別的物件的時候,我將『人類』該有的屬性 —— 『名字』以及『年紀』都輸入進去了。
底下,可以看到我將 clay 作為 Human 這個物件建立了起來。clay 這個物件的名字叫做 Clay,年紀則是 25 歲。
值得注意的是,如果該 class 底下的屬性並不打算讓外部瞧見的話,可以在屬性前加上 "__" 這樣的符號。
例如:
class Human(): def __init__(self, name, age): self.name = name self.__age = age if __name__ == '__main__': clay = Human('Clay', 25) print('Name:', clay.name) print('Age:', clay.__age)
Output:
AttributeError: 'Human' object has no attribute '__age'
Name: Clay
我們可以看到,name 這個屬性一樣被印了出來,可是相對而言,__age 則是報錯了。程式顯示找不到 Human 底下沒有這個屬性。
如此一來我們便可以建立不讓外部看到的屬性,只供內部使用的屬性。我認為這可以減少我們賦予物件屬性出錯的可能。
當然,其實我們也是可以展示這些『隱藏的』屬性。
class Human(): def __init__(self, name, age): self.name = name self.__age = age def who(self): return self.name def how_old(self): return self.__age if __name__ == '__main__': clay = Human('Clay', 25) print('Name:', clay.who()) print('Age:', clay.how_old())
Output:
Name: Clay
Age: 25
瞧!我們這次成功印出內部隱藏著的屬性了!只是我們繞了一圈,在 class 內部定義 function,然後再把內部屬性的值回傳而已!
繼承
緊接著,我們來介紹一下如何讓一個新建的 class 繼承之前存在的 class。
我們建立一個叫作 Police 的 class 當作新職業,當然,他擁有著作為 Human 的能力值。
class Human(): def __init__(self, name, age): self.name = name self.__age = age def who(self): return self.name def how_old(self): return self.__age class Police(Human): def __init__(self, name, age, power): super().__init__(name, age) self.power = power def PK(self): if self.power > 50: return True else: return False if __name__ == '__main__': clay = Police('Clay', 25, 70) print('Name:', clay.who()) print('Age:', clay.how_old()) print('PK:', clay.PK())
Output:
Name: Clay
Age: 25
PK: True
我們在 Police 定義的時候,放入要繼承的 class 名稱 —— 在這裡當然是 Human 這個類別。
然後我們使用 super().__init__() 放入我們身為人類的基本屬性,然後,給予 Police 這個職業的類別 power 這個新屬性。
底下執行的部份,我們只將 clay 作為 Police 這個類別建立,但我們可以看到,這個新類別 (Police) 一樣具有舊類別 (Human) 的屬性以及函式。
這樣大家是不是稍微明白基本的 class 運作方式了呢?
感想
終於寫到最後一堂課的筆記了。學習到 Python 的 class,並不僅是 Python 學習的一個里程碑,也是我個人紀錄的里程碑。
這是我第一個完成的系列文章。
Python 還有很多值得學習的部份。作為簡單易用的動態程式語言,它有著方便開發、撰寫迅速、套件眾多等等的優點,但與此相對,因為 GIL (全域解釋鎖) 的緣故,Python 沒辦法寫出真正高效的多執行緒程式。
但即便如此,我還是認為 Python 替程式員爭取到了開發時間。
在 Python 當中,還存在著許多可以學習的部份,請原諒我沒辦法涵蓋到所有的範圍。但從今以後,我還是會陸陸續續地介紹各式各樣 Python 的應用。
那都是些很有趣的題目。
希望各位也能多多參觀我的 Blog,同時不吝留言指正我的錯誤,謝謝大家!