当前位置: 首页 > news >正文

Python 中的 __new__深度解析

__new__是 Python 中最底层的对象创建机制,它比__init__更早被调用,真正负责分配并返回对象实例。理解它是掌握元类、单例、不可变类型定制等高级特性的基础。


一、__new__vs__init__的本质区别

classFoo:def__new__(cls,*args,**kwargs):print(f"[__new__] 分配内存,cls={cls}")instance=super().__new__(cls)# 创建实例returninstance# 必须 return!def__init__(self,value):print(f"[__init__] 初始化,self={self}")self.value=value obj=Foo(42)# [__new__] 分配内存,cls=<class 'Foo'># [__init__] 初始化,self=<__main__.Foo object>

关键区别:

__new____init__
调用时机实例创建之前实例创建之后
第一个参数cls(类本身)self(已有实例)
返回值必须返回实例必须返回None
职责分配空间,构造对象初始化属性

__init__只有在__new__返回了cls的实例时才会被调用。若返回其他类型,__init__会被跳过。


二、__new__的签名与调用链

object.__new__(cls[,*args,**kwargs])

Python 内部执行Foo(42)的等价逻辑是:

# type.__call__ 的内部行为(伪代码)def__call__(cls,*args,**kwargs):obj=cls.__new__(cls,*args,**kwargs)ifisinstance(obj,cls):# 只有返回 cls 的实例才调 __init__obj.__init__(*args,**kwargs)returnobj

下面是完整的对象创建生命周期:—

三、最重要的使用场景

1. 单例模式(Singleton)
classSingleton:_instance=Nonedef__new__(cls,*args,**kwargs):ifcls._instanceisNone:cls._instance=super().__new__(cls)returncls._instance# 始终返回同一个实例a=Singleton()b=Singleton()print(aisb)# True
2. 定制不可变类型

strinttuple等不可变类型必须在__new__中完成初始化,因为一旦创建就无法修改:

classUpperStr(str):def__new__(cls,value):returnsuper().__new__(cls,value.upper())# ⚠️ 不能在 __init__ 里改,str 是不可变的s=UpperStr("hello")print(s)# HELLOprint(type(s))# <class '__main__.UpperStr'>
3. 工厂模式 —— 根据参数返回不同类型
classShape:def__new__(cls,kind,*args):subclasses={"circle":Circle,"rect":Rect}target_cls=subclasses.get(kind,cls)returnsuper().__new__(target_cls)classCircle(Shape):passclassRect(Shape):passs=Shape("circle")print(type(s))# <class '__main__.Circle'>
4. 元类(Metaclass)中的__new__

元类的__new__控制类本身的创建(不是实例的创建):

classMeta(type):def__new__(mcs,name,bases,namespace):# 在类定义时,自动把所有方法名转大写new_ns={k.upper()ifnotk.startswith('_')elsek:vfork,vinnamespace.items()}returnsuper().__new__(mcs,name,bases,new_ns)classFoo(metaclass=Meta):defhello(self):return"hi"Foo().HELLO()# "hi" — 方法被重命名了

四、常见陷阱

陷阱1:忘记return

classBad:def__new__(cls):super().__new__(cls)# 没有 return!→ 返回 None# __init__ 不会被调用,obj 是 None

陷阱2:__init__的参数必须与__new__一致

# Python 会同时把参数传给 __new__ 和 __init__# 若签名不匹配会报 TypeErrorclassOk:def__new__(cls,x,y):# 接受 x, yreturnsuper().__new__(cls)def__init__(self,x,y):# 同样接受 x, y ✓self.x,self.y=x,y

陷阱3:super().__new__的参数

  • Python 3.3+ 后,object.__new__object.__init__中有一个接受了额外参数,另一个就会忽略多余参数(宽容机制)
  • 但自定义链中不要依赖这一行为,始终显式传递参数

五、__new____init_subclass____class_getitem__的关系

钩子触发时机典型用途
__new__每次实例化时控制实例创建
__init_subclass__定义子类时自动注册子类
__class_getitem__Foo[int]语法泛型支持
元类__new__定义类本身时修改类结构

总结

__new__的核心价值在于:在对象真正存在之前介入。当你需要控制的不是"对象初始化后的状态",而是"对象是哪个、是否创建、是什么类型"时,就该用__new__。日常开发中最实用的三个场景是:单例、不可变类型继承、工厂方法

http://www.jsqmd.com/news/718855/

相关文章:

  • CompressO:免费开源的跨平台视频图像压缩终极解决方案
  • 无纸记录仪品牌格局2026:国产厂商如何凭借灵活定制与高性价比实现市场主导 - 陈工日常
  • 2026年AI搜索优化与GEO生成式引擎优化服务商选型指南 - 优质企业观察收录
  • GoCaptcha 资源管理完全指南:字体、背景、图形素材的优化配置
  • 如何用VinXiangQi打造智能象棋助手:基于YOLOv5的完整指南
  • 终极指南:深度解密Kotlin编译器后端IR从指令选择到平台优化的全流程
  • ComfyUI-to-Python-Extension 部署指南:如何将转换后的Python脚本集成到生产环境中
  • 《赛博朋克2077》优化记录
  • 防水试验箱常见问题解答(2026最新专家版) - 速递信息
  • 2026 昆明财税公司哪家好?专业测评,实力推荐 - 品牌智鉴榜
  • 如何彻底掌控电脑风扇噪音:Fan Control终极使用指南
  • CSS Flex布局如何实现底部固定布局_利用flex-direction与margin实现footer贴底
  • GPSTest双频GNSS功能解析:提升定位精度的秘密武器
  • 10个rom-rb最佳实践技巧:从入门到专家级
  • 从石油抽油机到矿山机械:深入解析双圆弧齿轮的行业应用与选型避坑指南
  • 国产vs进口无纸记录仪深度解析:2026年在长期稳定性、软件友好度与总拥有成本上的较量 - 陈工日常
  • 2026年西北地区AI搜索优化服务商深度横评:甘肃腾广科技与竞品全景对比指南 - 优质企业观察收录
  • 3天打造专属桌面宠物:DyberPet框架让数字伙伴触手可及
  • Simplenote iOS入门指南:快速上手这款强大的开源笔记应用
  • 2026年江南电缆发展前景好的生产厂排名,杭州、烟台地区推荐 - 工业设备
  • SwiftyCam性能优化:5个实用技巧减少内存占用、提升拍摄速度
  • JRMSP-P8101电源模块
  • Dinghy完整指南:如何在macOS上构建5秒启动的Docker开发环境
  • 2026年学术写作双重突围:降重与AIGC风险防控收藏指南 - 降AI实验室
  • 告别云端依赖:手把手教你用MLC LLM在iPhone上本地运行大语言模型
  • 2026年托辊生产设备制造商哪家好,畅能机械靠谱之选 - 工业设备
  • Python 中的 __set__ 与 __set_name__ 深度解析
  • 收藏|2026 版 AI 大模型应用开发入门指南:行业转向、岗位解析、薪资曝光
  • 推荐一款神级 Claude Code 插件,暴涨 9.1 万 Star!
  • 如何掌握DLSS版本管理:DLSS Swapper完全指南与实战技巧