Loading comments...1.
2. 繼承:
3. Descriptor(描述器)與
3.1 Descriptor
3.2 使用描述器的類別
4.
Loading comments...
Python-003 Class
Python 物件導向程式設計(OOP)的進階特性與語法。除了基本的類別、建構子外,我們將來試著使用 slots 限制屬性、並透過描述器(Descriptor)來攔截屬性的讀取與寫入,還有使用 call、new、init 以及其他常見的魔術方法(例如 contains, str, iter)來自訂物件行為。廢話不多說,範例開始,一步步看 Python OOP 的強大之處吧!
Class 是什麼
在 Python 中,Class(類別
就像是一個「自訂的資料型態」或「範本」,可以用來描述某個特定物件可能包含的屬性(變數)與行為(方法)。如果把實例(object)比喻成一棟已落成的房子,那麼類別(Class)就像是建築藍圖,定義了該房子的格局、結構與功能,並由此來實際產生一棟又一棟「遵循相同設計」的房子。
1. Human
與類別基礎
- 類別變數:
cry
和happiness
是屬於整個類別共用的變數。所有Human
實例都可以存取它,並且共享相同的值。 - __slots__:
__slots__ = ('name', 'age')
限制此類別實例只能擁有name
、age
這兩個屬性,不允許動態新增其他屬性。- 使用
__slots__
可以幫助節省記憶體並提高存取速度,在需要大量建立實例或對效能要求較高的場景中很常見。
- __init__ (建構子):
- 在 Python 中,
__init__
是實例初始化方法,負責把參數綁定到實例上,例如self.name = name
。
- 在 Python 中,
- 實例方法:
show()
:簡單印出當前實例的屬性。
- 類別方法(@classmethod):
show_class(cls)
:可以透過類別或實例呼叫,但本質接收的是類別物件本身 (cls
),適合用來存取類別變數或執行與整個類別相關的操作。
- 靜態方法(@staticmethod):
show_static()
:跟類別方法一樣可以用「類別」或「實例」呼叫,但靜態方法完全不會接收任何隱含參數 (self
或cls
)。通常用於不需要存取任何類別或實例屬性的工具方法。
ex:
2. 繼承:Student
繼承 Human
- 繼承:
class Student(Human)
表示Student
類別繼承自Human
,因此擁有Human
的所有屬性與方法。- 繼承可以讓你在父類別基礎上擴充功能,而不用重複撰寫相同程式碼。
super()
:- 呼叫
super().__init__(name, age)
表示呼叫父類別 (Human
) 的__init__
,確保父類別初始化完成。
- 呼叫
- 方法覆寫(Override):
show()
在子類別中覆寫了父類別同名方法,但也透過super().show()
呼叫父類別的show()
, 然後再印出自己的屬性self.grade
。
ex:
3. Descriptor(描述器)與 __call__
範例
3.1 Descriptor NameValue
- Descriptor Protocol:在 Python 裏,只要類別同時實作
__get__
、__set__
或__delete__
,就是一個描述器。 - 屬性攔截/控制:
- 當
NameValue
被定義成某個類別的類別屬性時(例:name = NameValue()
),那個類別每次存取name
時,底層都會呼叫NameValue
裏面的__get__
/__set__
/__delete__
方法。 - 這可以用來實作額外的屬性驗證、轉換、或讀寫控制,比如說設定時先做檢查,刪除時做清理等等。
- 當
3.2 使用描述器的類別 Cat
name = NameValue()
:- 這裡
name
屬性就被接管到NameValue
描述器中。存取或設定Cat
實例的name
,底層都會呼叫描述器方法。
- 這裡
- __call__ 魔術方法:
- 讓物件實例可以「像函式一樣被呼叫」。當
aaron()
呼叫時,實際上會執行Cat.__call__()
。
- 讓物件實例可以「像函式一樣被呼叫」。當
ex:
4. __new__
與 metaclass 基礎
- __new__:
- 在 Python 中,
__new__
會在物件建立(記憶體配置)時最先被呼叫,並回傳該物件本身。 - 之後才會進行
__init__
做初始化。 - 在高度客製化物件行為或使用 metaclass 時,常需要重寫
__new__
。
- 在 Python 中,
- 魔術方法:
__contains__(self, item)
讓物件支援in
運算,例如'apple' in apple_obj
。__str__
自訂物件被print()
或str()
呼叫時的字串表示。__iter__
讓物件支援迭代,可用for item in apple_obj:
來迭代。
測試:
結語
若想深入了解 Python 進階 OOP 機制及各種奇妙寫法,可以參考官方文件或閱讀更多關於 metaclass、描述器的教學。這些語法特性或許不一定用得到,但在大型系統或框架層級往往能看到有前輩這樣使用,相信多多了解不吃虧。祝我們在 Python 裡玩得開心!