__init__ 是 Python 物件初始化的核心方法,決定實例建立後的初始狀態。本文從隱含超類 object 切入,探討初始化時機、參數靈活性、顯式優於隱式原則、繼承體系中 __init__ 協作與工廠函數演進。
class X: pass
X.__class__ #
X.__class__.__base__ #
所有類別隱含繼承 object,其 __init__ 預設為 pass。
class Rectangle:
def area(self):
return self.length * self.width
r = Rectangle()
r.length, r.width = 13, 8 # 執行期動態加入屬性
r.area() # 104
雖合法但違反「顯式優於隱式」,易導致 AttributeError、if 'x' in self.__dict__ 防禦性程式碼。
class Card:
def __init__(self, rank, suit):
self.suit = suit
self.rank = rank
self.hard, self.soft = self._points()
class NumberCard(Card):
def _points(self):
return int(self.rank), int(self.rank)
class AceCard(Card):
def _points(self):
return 1, 11
class FaceCard(Card):
def _points(self):
return 10, 10
__init__ 統一初始化共同屬性_points() 多型方法AceCard('A', '♠')
class Suit:
def __init__(self, name, symbol):
self.name = name
self.symbol = symbol
Club, Diamond, Heart, Spade = (
Suit('Club', '♣'), Suit('Diamond', '♦'),
Suit('Heart', '♥'), Suit('Spade', '♠')
)
cards = [AceCard('A', Spade), NumberCard('2', Spade)]
| 形式 | 範例 | 適用場景 |
|---|---|---|
| 位置參數 | Card('A', '♠') | 固定順序、少量參數 |
| 關鍵字參數 | Card(rank='A', suit='♠') | 參數多、順序易混、預設值 |
*args/**kwargs | def __init__(self, *a, **kw) | 框架基類、參數透傳 |
| Builder 模式 | CardBuilder().rank('A').suit('♠').build() | 複雜建構、可選步驟 |
# 簡單工廠
def create_card(rank, suit):
if rank == 'A': return AceCard(rank, suit)
elif rank in 'JQK': return FaceCard(rank, suit)
else: return NumberCard(rank, suit)
# 類方法工廠
class Card:
@classmethod
def from_string(cls, s): # "AS", "10H"
rank, suit = s[:-1], s[-1]
return create_card(rank, suit)
__init__ 顯式初始化所有實例屬性if 'attr' in self.__dict__ 防禦性檢查__init__ 處理共同初始化,子類擴充