Python 類別與物件

Python 類別與物件(Class and Object)

這篇 Python class 教學將帶你進入物件導向(OOP):把「資料」與「操作資料的函式」包在一起的程式設計方式。其實你早就在用物件了——字串、List、Dictionary 都是物件,它們的方法(appendsplit)就是包在類別裡的函式。現在輪到你自己定義。

名詞意義比喻
類別(class)物件的設計圖「學生」這個概念
物件(object/instance)依設計圖做出的實體小明、小華這些具體的學生
屬性(attribute)物件身上的資料姓名、成績
方法(method)物件能做的動作自我介紹、計算平均

定義類別與建立物件

class Student:
    def __init__(self, name, score):
        self.name = name        # 把參數存成物件的屬性
        self.score = score

    def introduce(self):
        print(f"我是 {self.name},考了 {self.score} 分")

s1 = Student("小明", 85)    # 建立物件(會自動呼叫 __init__)
s2 = Student("小華", 92)

s1.introduce()
s2.introduce()
print(s1.score + s2.score)

執行輸出:

我是 小明,考了 85 分
我是 小華,考了 92 分
177

__init__ 與 self 是什麼

最讓初學者困惑的兩個東西,一次講清楚:

__init__(建構式):建立物件時自動執行的方法,負責初始化屬性。Student("小明", 85) 的參數就是傳給它。

self(物件自己):方法的第一個參數,代表「呼叫這個方法的那個物件」。s1.introduce() 時,self 就是 s1s2.introduce() 時就是 s2——所以同一個方法能印出不同人的名字。定義方法時要寫 self,呼叫時不用傳,Python 自動帶入。

屬性可以隨時讀取與修改

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

s = Student("小明", 85)
print(s.score)

s.score = 90          # 直接修改屬性
print(s.score)

執行輸出:

85
90

方法之間互相呼叫

方法內用 self.方法名() 呼叫同物件的其他方法:

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount
        self.show()              # 呼叫自己的另一個方法

    def show(self):
        print(f"{self.owner} 餘額:{self.balance}")

acc = BankAccount("小明", 100)
acc.deposit(500)

執行輸出:

小明 餘額:600

類別屬性 vs 實例屬性

定義在 __init__ 外層的是「類別屬性」,所有物件共用——這是個常見陷阱:

class Student:
    school = "中山高中"      # 類別屬性:大家共用

    def __init__(self, name):
        self.name = name      # 實例屬性:各自獨立

s1 = Student("小明")
s2 = Student("小華")
print(s1.school, s2.school)

Student.school = "建國中學"   # 改類別屬性,所有物件都變
print(s1.school, s2.school)

執行輸出:

中山高中 中山高中
建國中學 建國中學

可變型別(List、dict)千萬不要當類別屬性,會發生跟「可變預設參數」一樣的共用災難。

常見錯誤

1. TypeError: introduce() takes 0 positional arguments but 1 was given

定義方法時忘了寫 self。Python 呼叫 s1.introduce() 時會自動把 s1 傳進去,方法卻沒有參數可以接。

2. AttributeError: ‘Student’ object has no attribute ‘xxx’

存取不存在的屬性:拼錯字,或該屬性只在某些條件下才被建立。屬性盡量都在 __init__ 裡初始化。

3. 忘記加括號建立物件

s = Student 只是把類別本身指給變數,s = Student("小明", 85) 才是建立物件。前者之後呼叫方法會出現奇怪的 TypeError。

總結

class 是設計圖、物件是實體;__init__ 負責初始化、self 代表物件自己(定義要寫、呼叫不用傳);實例屬性各自獨立、類別屬性全體共用(可變型別別放這)。下一篇學繼承——讓類別之間共享與擴充功能。

延伸閱讀