Python中的魔術方法__new__詳解
更新時間:2025年04月14日 15:33:25 作者:Yant224
這篇文章主要介紹了Python中的魔術方法__new__的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
一、核心意義與機制
1.1 構造過程原理

1.2 與 __init__ 對比
| 特性 | __new__ | __init__ |
|---|---|---|
| 方法類型 | 靜態(tài)方法 | 實例方法 |
| 返回值 | 必須返回實例對象 | 無返回值 |
| 調用時機 | 創(chuàng)建實例時首先調用 | 在 __new__ 之后調用 |
| 主要職責 | 控制實例創(chuàng)建過程 | 初始化實例屬性 |
二、核心功能解析
2.1 核心能力
- 控制實例創(chuàng)建過程
- 決定是否生成新實例
- 修改實例創(chuàng)建邏輯
- 實現(xiàn)設計模式底層支持
2.2 方法簽名
元類中的 __new__ 參數(shù)(示例 4.1)
- 樣例
class Meta(type):
def __new__(mcs, name, bases, attrs):
# 參數(shù)列表固定
return super().__new__(mcs, name, bases, attrs)- 參數(shù)解析表
| 參數(shù)名 | 類型 | 說明 |
|---|---|---|
| mcs | type | 元類自身(約定命名,類似 cls 代表類) |
| name | str | 要創(chuàng)建的類名(如 "MyClass") |
| bases | tuple | 基類列表(繼承的父類) |
| attrs | dict | 類屬性字典(包含方法、類變量等) |
調用邏輯
- 元類用于??創(chuàng)建類對象??(不是實例對象)
- 參數(shù)由解釋器在定義類時自動傳入
super().__new__最終調用type.__new__生成類對象
不可變類型子類的 __new__(示例 3.2)
樣例
class ImmutableStr(str):
def __new__(cls, value):
return super().__new__(cls, processed_value)- 參數(shù)解析表
| 參數(shù)名 | 類型 | 說明 |
|---|---|---|
| cls | type | 當前類對象(ImmutableStr) |
| value | Any | 用戶自定義參數(shù)(初始化輸入值) |
調用邏輯
- 繼承自不可變類型(
str/int/tuple等) - 必須通過
__new__完成實例創(chuàng)建 super().__new__調用父類(str)的構造方法- 參數(shù)需匹配父類
__new__的要求(如str需要傳入初始化字符串)
可變類型普通類的 __new__(示例 3.1)
樣例
class Singleton:
def __new__(cls, *args, ?**?kwargs):
return super().__new__(cls)- 參數(shù)解析表
| 參數(shù)名 | 類型 | 說明 |
|---|---|---|
| cls | ` | 當前類對象(Singleton) |
| *args | tuple | 位置參數(shù)(與 __init__ 共享參數(shù)) |
| ?**?kwargs | dict | 關鍵字參數(shù)(與 __init__ 共享參數(shù)) |
調用邏輯
- 普通類的實例創(chuàng)建流程
super().__new__調用object.__new__生成實例- 參數(shù)需與
__init__方法兼容
2.3 參數(shù)傳遞關系圖示

2.4 核心記憶要點
??元類 __new__ 的四個參數(shù)是固定結構??
- 用于構建類對象(類的模板)
- 參數(shù)由解釋器自動填充
??普通類 __new__ 第一個參數(shù)必為 cls??
- 后續(xù)參數(shù)需與
__init__匹配 - 不可變類型需要完全重寫參數(shù)列表
??super().__new__ 的參數(shù)必須與父類一致??
- 元類中:
super().__new__(mcs, name, bases, attrs) - 普通類中:
super().__new__(cls[, ...])
三、典型應用場景
3.1 單例模式實現(xiàn)
class Singleton:
_instance = None
def __new__(cls, *args, ?**?kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
a = Singleton()
b = Singleton()
print(a is b) # True3.2 不可變類型擴展
class ImmutableStr(str):
def __new__(cls, value):
# 預處理字符串
processed = value.strip().upper()
return super().__new__(cls, processed)
s = ImmutableStr(" hello ")
print(s) # "HELLO"3.3 對象池技術
class ConnectionPool:
_pool = []
_max_size = 5
def __new__(cls):
if len(cls._pool) < cls._max_size:
obj = super().__new__(cls)
cls._pool.append(obj)
return obj
return cls._pool.pop(0)
conn1 = ConnectionPool()
conn2 = ConnectionPool()四、高級應用技巧
4.1 元類協(xié)作
class Meta(type):
def __new__(mcs, name, bases, attrs):
# 添加類屬性
attrs['version'] = 1.0
return super().__new__(mcs, name, bases, attrs)
class MyClass(metaclass=Meta):
pass
print(MyClass.version) # 1.04.2 參數(shù)預處理
class SmartTuple(tuple):
def __new__(cls, iterable):
# 過濾非數(shù)字元素
filtered = (x for x in iterable if isinstance(x, (int, float)))
return super().__new__(cls, filtered)
t = SmartTuple([1, 'a', 3.14, None])
print(t) # (1, 3.14)五、繼承體系中的使用
5.1 繼承鏈處理
class Base:
def __new__(cls, *args, ?**?kwargs):
print(f"Creating {cls.__name__}")
return super().__new__(cls)
class Child(Base):
pass
c = Child() # 輸出 "Creating Child"5.2 多繼承處理
class A:
def __new__(cls, *args, ?**?kwargs):
print("A's __new__")
return super().__new__(cls)
class B:
def __new__(cls, *args, ?**?kwargs):
print("B's __new__")
return super().__new__(cls)
class C(A, B):
def __new__(cls, *args, ?**?kwargs):
return A.__new__(cls)
obj = C() # 輸出 "A's __new__"六、注意事項與調試
6.1 常見錯誤
class ErrorCase:
def __new__(cls):
# 錯誤:忘記返回實例
print("Creating instance") # ? 無返回值
def __init__(self):
print("Initializing")
e = ErrorCase() # TypeError6.2 調試技巧
class DebugClass:
def __new__(cls, *args, ?**?kwargs):
print(f"__new__ args: {args}")
instance = super().__new__(cls)
print(f"Instance ID: {id(instance)}")
return instance
def __init__(self, value):
print(f"__init__ value: {value}")
d = DebugClass(42)七、性能優(yōu)化建議
7.1 對象緩存策略
class ExpensiveObject:
_cache = {}
def __new__(cls, config):
key = hash(frozenset(config.items()))
if key not in cls._cache:
instance = super().__new__(cls)
instance._init(config)
cls._cache[key] = instance
return cls._cache[key]
def __init__(self, config):
# 避免重復初始化
self.config = config最佳實踐總結??
- 優(yōu)先使用
super().__new__保證繼承鏈正常 - 修改不可變類型必須使用
__new__ - 單例模式要處理好線程安全問題
- 避免在
__new__中做耗時操作
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Qt通過QGraphicsview實現(xiàn)簡單縮放及還原效果
本文主要介紹通過QGraphicsview實現(xiàn)簡單的縮放以及縮放后還原原始大小,通過scale可以對view進行放大或縮小,具體內容詳情跟隨小編一起看看吧2021-09-09
python 設置xlabel,ylabel 坐標軸字體大小,字體類型
這篇文章主要介紹了python 設置xlabel,ylabel 坐標軸字體大小,字體類型,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-07-07

