在 Python 面向?qū)ο缶幊讨?,魔術(shù)方法(Magic Methods,又稱特殊方法)是一類以雙下劃線__包裹的特殊函數(shù),它們隱藏在類的底層,支撐著 Python 的核心語(yǔ)法特性(如對(duì)象創(chuàng)建、運(yùn)算符重載、迭代等)。理解魔術(shù)方法,尤其是__init__與__new__這兩個(gè)與對(duì)象創(chuàng)建密切相關(guān)的方法,是掌握 Python 高級(jí)編程的關(guān)鍵。小編將詳解魔術(shù)方法的本質(zhì),重點(diǎn)拆解__init__與__new__的區(qū)別,助你深入理解 Python 對(duì)象的創(chuàng)建機(jī)制。
一、魔術(shù)方法:Python 面向?qū)ο蟮?“隱形引擎”
魔術(shù)方法并非由開發(fā)者主動(dòng)調(diào)用,而是在特定場(chǎng)景下由 Python 解釋器自動(dòng)觸發(fā),它們?yōu)轭愘x予了 “特殊能力”,讓 Python 代碼更簡(jiǎn)潔、更符合直覺(jué)。
(一)魔術(shù)方法的核心特征
命名規(guī)范:均以雙下劃線開頭和結(jié)尾(如__init__、__str__、__add__),避免與普通方法重名;
自動(dòng)觸發(fā):無(wú)需手動(dòng)調(diào)用,滿足條件時(shí)自動(dòng)執(zhí)行。例如調(diào)用print(obj)時(shí),會(huì)自動(dòng)觸發(fā)obj.__str__()方法;使用+運(yùn)算符時(shí),會(huì)觸發(fā)__add__()方法;
功能基礎(chǔ):支撐 Python 的核心語(yǔ)法,如__init__參與對(duì)象初始化、__iter__支持迭代、__getitem__支持索引訪問(wèn),沒(méi)有魔術(shù)方法,許多 Python 特性將無(wú)法實(shí)現(xiàn)。
(二)常見魔術(shù)方法示例
__str__:定義對(duì)象的字符串表示,print(obj)或str(obj)時(shí)觸發(fā),返回用戶友好的字符串;
__add__:重載+運(yùn)算符,實(shí)現(xiàn)自定義對(duì)象的加法邏輯;
__len__:定義len(obj)時(shí)的返回值,支持獲取自定義對(duì)象的 “長(zhǎng)度”;
__init__與__new__:均與對(duì)象創(chuàng)建相關(guān),但職責(zé)不同,是本文重點(diǎn)解析的對(duì)象。
二、__init__與__new__的核心差異:對(duì)象創(chuàng)建的 “兩步曲”
Python 創(chuàng)建對(duì)象的過(guò)程分為 “創(chuàng)建空對(duì)象” 和 “初始化對(duì)象屬性” 兩步,__new__負(fù)責(zé)第一步,__init__負(fù)責(zé)第二步,兩者在調(diào)用時(shí)機(jī)、參數(shù)、返回值等方面存在本質(zhì)區(qū)別。
(一)調(diào)用時(shí)機(jī):先__new__,后__init__
__new__:是類的靜態(tài)方法(無(wú)需手動(dòng)加@staticmethod裝飾器),在對(duì)象被創(chuàng)建之前調(diào)用,其核心作用是 “生成一個(gè)空的對(duì)象實(shí)例”,是對(duì)象的 “誕生器”;
__init__:是對(duì)象的實(shí)例方法,在__new__創(chuàng)建出空對(duì)象后調(diào)用,作用是 “為空白對(duì)象初始化屬性”(如賦值實(shí)例變量),是對(duì)象的 “裝修工”。
示例:通過(guò)打印驗(yàn)證調(diào)用順序
TypeScript取消自動(dòng)換行復(fù)制
class MyClass:
def __new__(cls, *args, **kwargs):
print("__new__被調(diào)用:創(chuàng)建空對(duì)象")
# 調(diào)用父類的__new__生成空對(duì)象并返回
return super().__new__(cls)
def __init__(self, name):
print("__init__被調(diào)用:初始化屬性")
self.name = name # 為空白對(duì)象添加name屬性
# 創(chuàng)建對(duì)象,觀察打印順序
obj = MyClass("Test")
輸出結(jié)果:
TypeScript取消自動(dòng)換行復(fù)制
__new__被調(diào)用:創(chuàng)建空對(duì)象
__init__被調(diào)用:初始化屬性
可見,__new__先執(zhí)行,生成空對(duì)象后,__init__才執(zhí)行并初始化屬性。
(二)參數(shù)與返回值:一個(gè)創(chuàng)建,一個(gè)初始化
參數(shù)差異:
__new__:第一個(gè)參數(shù)是cls(代表當(dāng)前類),后續(xù)參數(shù)與__init__一致,用于接收創(chuàng)建對(duì)象時(shí)傳入的參數(shù)(如示例中的name);
__init__:第一個(gè)參數(shù)是self(代表__new__創(chuàng)建的空對(duì)象),后續(xù)參數(shù)用于初始化屬性,參數(shù)需與__new__傳遞的參數(shù)匹配。
返回值差異:
__new__:必須返回一個(gè) “類的實(shí)例對(duì)象”(通常是調(diào)用父類super().__new__(cls)的結(jié)果),若不返回實(shí)例,__init__將不會(huì)被調(diào)用(因?yàn)闆](méi)有對(duì)象可初始化);
__init__:無(wú)返回值(默認(rèn)返回None),若強(qiáng)行返回非None值,Python 會(huì)拋出TypeError,因?yàn)樗穆氊?zé)是初始化屬性,而非返回新對(duì)象。
反例:__new__不返回實(shí)例時(shí),__init__不執(zhí)行
TypeScript取消自動(dòng)換行復(fù)制
class NoInitClass:
def __new__(cls, name):
print("__new__被調(diào)用,但不返回實(shí)例")
# 未返回實(shí)例,__init__不會(huì)執(zhí)行
return None
def __init__(self, name):
print("__init__不會(huì)被調(diào)用")
obj = NoInitClass("Test") # 僅輸出“__new__被調(diào)用,但不返回實(shí)例”
(三)作用與使用場(chǎng)景:一個(gè)控制創(chuàng)建,一個(gè)完善屬性
__new__:主要用于 “控制對(duì)象的創(chuàng)建過(guò)程”,如實(shí)現(xiàn)單例模式(確保一個(gè)類只有一個(gè)實(shí)例)、限制類的實(shí)例化(如禁止創(chuàng)建子類實(shí)例)、自定義實(shí)例的內(nèi)存分配等,場(chǎng)景較特殊,日常開發(fā)中較少重寫;
__init__:用于 “為實(shí)例初始化屬性”,是日常開發(fā)中最常用的魔術(shù)方法,幾乎所有自定義類都會(huì)重寫__init__,為對(duì)象添加必要的實(shí)例變量(如self.name、self.age)。
示例:用__new__實(shí)現(xiàn)單例模式
TypeScript取消自動(dòng)換行復(fù)制
class Singleton:
_instance = None # 存儲(chǔ)唯一實(shí)例
def __new__(cls, *args, **kwargs):
if cls._instance is None:
# 若實(shí)例不存在,創(chuàng)建并保存
cls._instance = super().__new__(cls)
return cls._instance # 始終返回同一個(gè)實(shí)例
def __init__(self, name):
self.name = name # 多次初始化會(huì)覆蓋屬性,但實(shí)例唯一
# 測(cè)試:兩次創(chuàng)建的對(duì)象是同一個(gè)實(shí)例
obj1 = Singleton("First")
obj2 = Singleton("Second")
print(obj1 is obj2) # 輸出:True(實(shí)例相同)
print(obj1.name) # 輸出:Second(被第二次初始化覆蓋)
魔術(shù)方法是 Python 面向?qū)ο缶幊痰?“隱形基石”,支撐著對(duì)象創(chuàng)建、運(yùn)算符重載等核心功能,而__init__與__new__是對(duì)象創(chuàng)建過(guò)程中的關(guān)鍵兩步:__new__先創(chuàng)建空對(duì)象,__init__后初始化屬性,兩者分工明確、順序固定。