Skip to content

[Python] 基本教學(15) Class 類別

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,同時不吝留言指正我的錯誤,謝謝大家!


References


Read More

Leave a Reply