每張訂單都帶著飲料、杯型和價格,三個函式把它們分開傳來傳去。類可以讓一個物件把它們裝在一起。這個物件應該能為自己做什麼?
類(class)是建立物件的藍圖。物件用屬性儲存資料,用方法提供行為。先從訂單這樣的小記錄開始,一次只加一個方法。 你還會區分類屬性與實例屬性、在 __init__ 中守住不變數,並寫出有用的 __repr__。
定義類
class 關鍵字建立藍圖。建立新物件時會執行 __init__。self 指向目前這個物件,屬性通過 self.name 賦值。
class Order:
def __init__(self, drink, price):
self.drink = drink
self.price = price
order = Order("latte", 4.5)
print(order.drink)
print(order.price)一個小類
添加方法
方法就是定義在類裡的函式,第一個參數是 self。它可以讀取物件屬性並回傳結果;呼叫時不需要手動傳入 self。
class Order:
def __init__(self, drink, price, quantity=1):
self.drink = drink
self.price = price
self.quantity = quantity
def total(self):
return self.price * self.quantity
print(Order("latte", 4.5, 2).total())帶預設值的方法
建立獨立物件
每個實例都有自己的屬性值。走訪物件列表,通常比維護幾個平行列表更清楚。逐個列印欄位,檢查每個物件儲存了什麼。
class Order:
def __init__(self, drink, price):
self.drink = drink
self.price = price
orders = [Order("latte", 4.5), Order("tea", 3.0)]
for order in orders:
print(order.drink, order.price)物件列表
類屬性是所有實例共用的
在類體裡賦值的屬性屬於類,不屬於某個物件。可變的類屬性會被所有實例共用。每個物件自己的預設值要放進 __init__;只有確實該共用的值才留在類上。
class Order:
tags = []
def __init__(self, drink):
self.drink = drink
first = Order("latte")
second = Order("tea")
first.tags.append("gift")
print(second.tags)
print(first.tags is second.tags)所有訂單共用同一個列表
物件建立時就驗證不變數
物件不應該以非法狀態存在。在 __init__ 裡檢查價格和數量,帶著壞值拋出 ValueError。呼叫方只需處理一個清楚的失敗,而不是過很久才發現總價是負數。
class Order:
def __init__(self, drink, price):
if price < 0:
raise ValueError(f"negative price: {price}")
self.drink = drink
self.price = price
for price in [4.5, -1]:
try:
order = Order("latte", price)
print(order.drink, order.price)
except ValueError as error:
print(type(error).__name__, error)在物件存在之前拒絕壞值
__repr__ 應該幫助偵錯
沒有 __str__ 時,print(order) 會退回到 __repr__。好的 __repr__ 顯示類名和能識別物件的欄位。它面向開發者,所以要明確,不要寫成一句營銷文案。
class Order:
def __init__(self, drink, price, quantity=1):
self.drink = drink
self.price = price
self.quantity = quantity
def __repr__(self):
return f"Order(drink={self.drink!r}, price={self.price}, quantity={self.quantity})"
print(Order("latte", 4.5, 2))顯示類名和識別欄位
本課要點
- 類定義物件的形狀。
- __init__ 初始化新實例。
- self 指向目前實例。
- 方法可以讀取屬性並回傳計算結果。
- 可變預設值放進 __init__;類屬性由所有實例共用。
常見錯誤
- 定義方法時忘記寫 self。
- 只定義了類,卻從未呼叫它建立物件。
- 不小心讓多個實例共用同一個可變屬性。
- 把類級別的列表當成每個物件自己的標籤列表。
建立帶 drink 和 price 的 Order 類,再為兩個訂單列印格式化總價。
動手試試
改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。
練習本課
12 道題,作答後立即看到解釋。