iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
Software Development

跟著 OXXO 一起學 Python系列 第 26

( Day 13.1 ) Python 類別 class

  • 分享至 

  • xImage
  •  

當學習 Python 到某種程度後,就會開始進入物件導向的領域,而「類別」就是學習物件導向的基礎,這篇教學將會介紹 Python 裡的類別 class,並進一步說明類別和物件的關係。

原文參考:類別 class

本篇使用的 Python 版本為 3.7.12,所有範例可使用 Google Colab 實作,不用安裝任何軟體 ( 參考:使用 Google Colab )

什麼是類別 class?

類別,可以比喻成一張「藍圖」,不同的藍圖會有不同的「屬性」,根據不同的屬性,就會建構出不同的物體。或者也可將類別想像成一個「人」,不同的人會有不同的「特徵」( 屬性 ),根據不同的特徵,就會產生不同樣的人

舉例來說,下方的程式碼建立了一個名為 human ( 人 ) 的類別,類別預設有四個屬性,分別是兩個眼睛 eye、兩個耳朵 ear、一個鼻子 nose 和一張嘴巴 mouth,接著透過這個類別誕生了一個特定的人 oxxo,這個人就會具有對應的屬性 ( 後面會介紹如何建立類別 )。

class human():
  def __init__(self):  # 建立預設屬性的寫法
    self.eye = 2       # 兩個眼睛
    self.ear = 2       # 兩個耳朵
    self.nose = 1      # 一個鼻子
    self.mouth = 1     # 一張嘴巴

oxxo = human()         # 製作一個名為 oxxo 的物件
print(oxxo.eye)        # 得到 2 ( 印出 oxxo 的 eye 屬性 )。

什麼是物件 object?

在 Python 裡的任何東西 ( 數字、文字、函式...等 ) 都是物件,只是 Python 預設會將大部份物件的機制隱藏,只顯示最常使用的方法,除非有特殊需求,不然不需要更動到預設物件的行為。

什麼是物件呢?物件是一種自訂的資料結構,裡面可能包含了各種變數、屬性、函式或方法,一個物件可以透過他的屬性或方法,定義他和別的物件進行互動。

建立類別

建立類別的方式類似建立一個函式,差別在於函式使用 def 開頭,而類別使用 class 開頭,下方的程式碼會建立一個「空」的類別 human ( 很像一個人在最開始只是一個細胞,身上什麼器官都還沒長出來 ):

class human():
    pass        # 使用 pass 可以建立一個空類別

接著使用建立類別的預設方法「__init__」( 注意前後是兩條底線 ),將預設的屬性加入類別裡。

  • def __init__(self) 預設帶有一個 self 參數,代表透過類別建立的物件本體,內容使用「.屬性」就能將指定的屬性加入類別中。
  • __init__ 可以不用定義,但如果需要有一些預設的屬性,就可以定義在裡面
class human():
    def __init__(self):  # 建立預設屬性的寫法
        self.eye = 2       # 兩個眼睛
        self.ear = 2       # 兩個耳朵
        self.nose = 1      # 一個鼻子
        self.mouth = 1     # 一張嘴巴

除了預設的屬性,也可以自訂屬性,下方的例子定義了 say 和 play 兩個函式作為 human 的屬性,執行後,就等同於一個名為 oxxo 的人說話和玩棒球。

注意,字定義屬性的第一個參數也都必須是 self

class human():
    def __init__(self):
        self.eye = 2
        self.ear = 2
        self.nose = 1
        self.mouth = 1
    def say(self, msg):      # 定義 say
        print(msg)
    def play(self, thing):   # 定義 play
        print(thing)

oxxo = human()
oxxo.say('hello')          # hello
oxxo.play('baseball')      # baseball

屬性除了可以定義在類別裡,也可以從外部定義,下面的程式碼額外定義了手 hand 和腳 leg 兩個屬性。

class human():
    def __init__(self):
        self.eye = 2
        self.ear = 2
        self.nose = 1
        self.mouth = 1
    def say(self, msg):
        print(msg)
    def play(self, thing):
        print(thing)

human.hand = 2    # 定義 hand 屬性
human.leg = 2     # 定義 leg 屬性

oxxo = human()
print(oxxo.hand)  # 2
print(oxxo.leg)   # 2

剛剛有提到 self 這個參數,這個參數代表「透過類別建立的物件本體」,使用 self 可以讀取到這個物件的所有屬性,下方的例子從外部定義了 oxxo.name 的屬性,在 human 裡就能使用 self.name 取得這個屬性。

class human():
    def __init__(self):
        self.eye = 2
        self.ear = 2
        self.nose = 1
        self.mouth = 1
    def say(self, msg):
        print(f'{self.name} say: {msg}')   # 使用 self.name 取得 name 屬性的值
    def play(self, thing):
        print(thing)

oxxo = human()
oxxo.name = 'oxxo'   # 設定 name 屬性
oxxo.say('hello')    # oxxo say: hello

多個物件同一個類別

一個類別可以產生多個物件 ( 人 human 的類別可以產生無數不同的人 ),每個物件產生後,也可以定義自己特殊的屬性,就如同人誕生後,雖然都有眼睛鼻子嘴巴,但某些人會去學畫畫,某些人會去學鋼琴,下方的程式碼會產生oxxo 和 gkpen 兩個不同的人,oxxo 會自定義 age 屬性,gkpen 會自定義 weight 屬性。

class human():
    def __init__(self):
        self.eye = 2
        self.ear = 2
        self.nose = 1
        self.mouth = 1
    def say(self, msg):
        print(f'{self.name} say: {msg}')
    def play(self, thing):
        print(thing)

oxxo = human()        # 定義 oxxo
gkpen = human()       # 定義 gkpen
oxxo.name = 'oxxo'    # oxxo 的名字叫做 oxxo
oxxo.age = 18         # oxxo 的 age 為 18

gkpen.name = 'gkpen'  # gkpen 的名字叫做 gkpen
gkpen.weight = 70     # gkpen 的 weight 為 70

oxxo.say('hello')    # oxxo say: hello
print(oxxo.age)      # 18
gkpen.say('song')    # gkpen say: song
print(gkpen.weight)  # 70

如果覺得這樣子定義比較麻煩,也可以在建立類別時,預先設定好一些參數,接著透過類別建立物件時,在做動態的調整,例如下方的例子,在 init 裡建立 age、weight 的參數,建立物件時就能動態傳入。

class human():
    def __init__(self, age, weight):    # 新增 age 和 weight 參數
        self.eye = 2
        self.ear = 2
        self.nose = 1
        self.mouth = 1
        self.age = age             # 讀取參數,變成屬性
        self.weight = weight       # 讀取參數,變成屬性
    def say(self, msg):
        print(f'{self.name} say: {msg}')
    def play(self, thing):
        print(thing)

oxxo = human(18, 68)            # 建立物件時,設定參數數值
gkpen = human(15, 70)           # 建立物件時,設定參數數值
print(oxxo.age, oxxo.weight)    # 18, 68
print(gkpen.age, gkpen.weight)  # 15, 70

覆寫屬性

如果從外部定義了和類別屬性名稱相同的屬性,就會覆寫內部屬性,下方的例子,從外部定義了 oxxo.play 的屬性,就覆寫原本的 play 屬性。

class human():
    def __init__(self):
        self.eye = 2
        self.ear = 2
        self.nose = 1
        self.mouth = 1
    def say(self, msg):
        print(f'{self.name} say: {msg}')
    def play(self, thing):
        print(thing)

oxxo = human()
oxxo.play = '???'  # 覆寫 play 屬性
print(oxxo.play)   # ???

@property 唯讀屬性

如果在類別裡有些屬性不希望被外部更動,就能夠使用 @property 的裝飾器,將該屬性設為唯讀屬性,下方的例子,oxxo.a 可以將原本的 a 屬性換成 12345,但 oxxo.b 就無法更動 b 屬性,因為 b 屬性已經變成唯讀屬性。

class a:
    def a(self):
        return 'aaaaa'
    @property
    def b(self):
        return 'bbbbb'

oxxo = a()
oxxo.a = '12345'
print(oxxo.a)   # 12345
oxxo.b = '12345'
print(oxxo.b)   # 發生錯誤  can't set attribute

更多教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我有個超過一千篇教學的 STEAM 教育學習網,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 12.2 ) Python 內建函式 ( eval 和 exec )
下一篇
( Day 13.2 ) Python 繼承 inheritance
系列文
跟著 OXXO 一起學 Python101
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言