Python中的?__init__、__new__?和?__call__示例詳解
這三個特殊方法是 Python 面向?qū)ο缶幊讨械暮诵臉?gòu)造機制,分別在對象生命周期的不同階段發(fā)揮作用:
1.__init__方法:對象初始化器
作用:初始化新創(chuàng)建的實例對象
調(diào)用時機:在
__new__創(chuàng)建實例之后自動調(diào)用參數(shù):第一個參數(shù)必須是
self(指向新實例)返回值:無(必須返回
None)核心職責(zé):
設(shè)置實例屬性的初始值
執(zhí)行必要的初始化操作
不負責(zé)創(chuàng)建對象本身
class Person: def __init__(self, name, age): print("__init__ called") self.name = name # 設(shè)置實例屬性 self.age = age # 使用 p = Person("Alice", 30) # 輸出:__init__ called print(p.name) # Alice關(guān)鍵點:
每個類可以定義自己的
__init__如果未定義,繼承父類的
__init__可以調(diào)用父類的
__init__:super().__init__(args)不是構(gòu)造函數(shù)(實際創(chuàng)建對象的是
__new__)
2.__new__方法:對象創(chuàng)建器
作用:實際創(chuàng)建類的新實例
調(diào)用時機:在
__init__之前自動調(diào)用參數(shù):第一個參數(shù)必須是
cls(指向當前類)返回值:必須返回創(chuàng)建好的實例對象
核心職責(zé):
控制實例創(chuàng)建過程
決定是否返回新實例或已有實例
可以返回其他類的實例
class Singleton: _instance = None def __new__(cls, *args, **kwargs): print("__new__ called") if not cls._instance: # 創(chuàng)建新實例(調(diào)用父類的__new__) cls._instance = super().__new__(cls) return cls._instance # 返回實例(新或已有) def __init__(self, value): print("__init__ called") self.value = value # 使用 s1 = Singleton(10) # 輸出: __new__ called -> __init__ called s2 = Singleton(20) # 輸出: __new__ called -> __init__ called print(s1 is s2) # True(相同實例) print(s1.value) # 20(注意:__init__被再次調(diào)用?。?關(guān)鍵點:
必須返回有效的對象實例
如果返回非當前類實例,
__init__不會被調(diào)用常用場景:單例模式、不可變類型子類化
元類中
__new__創(chuàng)建的是類對象本身
3.__call__方法:對象調(diào)用器
作用:使類的實例可以像函數(shù)一樣被調(diào)用
調(diào)用時機:當實例后加
()時自動調(diào)用參數(shù):第一個參數(shù)必須是
self(指向?qū)嵗?/p>返回值:任意類型值
核心職責(zé):
定義實例作為函數(shù)的行為
實現(xiàn)裝飾器類
創(chuàng)建有狀態(tài)的函數(shù)對象
class Adder:
def __init__(self, base):
self.base = base
def __call__(self, x):
print("__call__ invoked")
return self.base + x
# 使用
add5 = Adder(5) # 創(chuàng)建可調(diào)用對象
print(add5(3)) # 輸出: __call__ invoked -> 8
print(add5(10)) # 輸出: __call__ invoked -> 15高級應(yīng)用:裝飾器類
class TraceCalls:
def __init__(self, func):
self.func = func
self.call_count = 0
def __call__(self, *args, **kwargs):
self.call_count += 1
print(f"Call #{self.call_count} to {self.func.__name__}")
return self.func(*args, **kwargs)
@TraceCalls
def multiply(a, b):
return a * b
print(multiply(3, 4))
# 輸出:
# Call #1 to multiply
# 12
print(multiply(5, 6))
# 輸出:
# Call #2 to multiply
# 30三者的協(xié)作流程
class Example:
def __new__(cls, *args, **kwargs):
print("1. __new__: Creating instance")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("2. __init__: Initializing instance")
self.value = value
def __call__(self, multiplier):
print("3. __call__: Invoking instance")
return self.value * multiplier
# 完整生命周期
e = Example(10)
# 輸出:
# 1. __new__: Creating instance
# 2. __init__: Initializing instance
result = e(5)
# 輸出:
# 3. __call__: Invoking instance
print(result) # 50關(guān)鍵對比表
| 特性 | __new__ | __init__ | __call__ |
|---|---|---|---|
| 角色 | 對象創(chuàng)建器 | 對象初始化器 | 對象調(diào)用器 |
| 調(diào)用時機 | 創(chuàng)建實例時(最先) | __new__ 之后 | 實例被調(diào)用時 |
| 首參數(shù) | cls (類引用) | self (實例引用) | self (實例引用) |
| 返回值 | 必須返回實例對象 | 必須返回 None | 可返回任意值 |
| 主要用途 | 控制實例創(chuàng)建過程 | 初始化實例屬性 | 使實例可像函數(shù)一樣調(diào)用 |
| 是否必需 | 不定義則用 object.__new__ | 不定義則跳過初始化 | 不定義則實例不可調(diào)用 |
| 典型場景 | 單例模式、不可變類型 | 常規(guī)對象初始化 | 裝飾器類、函數(shù)對象 |
高級應(yīng)用場景
1. 不可變類型擴展
class UppercaseStr(str):
def __new__(cls, value):
# 在創(chuàng)建前修改值
return super().__new__(cls, value.upper())
s = UppercaseStr("hello")
print(s) # "HELLO"(不可變對象在創(chuàng)建時確定值)2. 對象工廠
class Animal:
def __new__(cls, animal_type, *args):
if animal_type == "dog":
return Dog(*args)
elif animal_type == "cat":
return Cat(*args)
raise ValueError(f"Unknown animal: {animal_type}")
class Dog:
def __init__(self, name):
self.name = name
class Cat:
def __init__(self, name):
self.name = name
d = Animal("dog", "Buddy")
print(type(d), d.name) # <class '__main__.Dog'> Buddy3. 帶狀態(tài)的裝飾器
class Retry:
def __init__(self, max_attempts=3):
self.max_attempts = max_attempts
def __call__(self, func):
def wrapper(*args, **kwargs):
for attempt in range(1, self.max_attempts+1):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Attempt {attempt} failed: {e}")
raise RuntimeError("All attempts failed")
return wrapper
@Retry(max_attempts=2)
def risky_operation():
import random
if random.random() < 0.7:
raise ValueError("Random failure")
return "Success"
print(risky_operation())常見陷阱與解決方案
1. __init__ 中忘記返回 None
class Mistake:
def __init__(self):
return 42 # TypeError: __init__() should return None2.__new__ 忘記返回實例
class BadClass:
def __new__(cls):
print("Forgot to return instance") # 返回None -> TypeError3.單例模式中的重復(fù)初始化
解決方案:使用標志位控制
class SafeSingleton:
_instance = None
_initialized = False
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if not self.__class__._initialized:
# 初始化代碼
self.__class__._initialized = True4.__call__ 與 __init__ 參數(shù)混淆
掌握這三個特殊方法的區(qū)別和協(xié)作機制,能夠讓你更精細地控制 Python 對象的整個生命周期,實現(xiàn)更高級的設(shè)計模式。
總結(jié)
到此這篇關(guān)于Python中的 __init__、__new__ 和 __call__的文章就介紹到這了,更多相關(guān)Python __init__、__new__ 和 __call__內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python中的魔術(shù)方法__new__詳解
- Python中__new__()方法適應(yīng)及注意事項詳解
- python中__new__和__init__的實現(xiàn)
- python __init__與 __new__的區(qū)別
- Python中class內(nèi)置方法__init__與__new__作用與區(qū)別解析
- 詳解Python中__new__方法的作用
- Python 中類的構(gòu)造方法 __New__的妙用
- Python中__new__和__init__的區(qū)別與聯(lián)系
- Python 用__new__方法實現(xiàn)單例的操作
- python中__new__函數(shù)的具體使用
相關(guān)文章
解決Pycharm在Debug的時候一直“Connected”沒有下一步動作問題
這篇文章主要介紹了解決Pycharm在Debug的時候一直“Connected”沒有下一步動作問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
python獲取android設(shè)備的GPS信息腳本分享
這篇文章主要介紹了python獲取android設(shè)備的GPS信息腳本分享,本文直接給出實現(xiàn)代碼,需要的朋友可以參考下2015-03-03
python中CURL 和python requests的相互轉(zhuǎn)換實現(xiàn)
本文主要介紹了python中CURL 和python requests的相互轉(zhuǎn)換實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03

