__new__ 是真正负责分配内存并返回实例的方法,必须返回实例对象,否则因 __init__ 缺少 self 参数而报错;它在 __init__ 前执行,用于拦截、复用或定制实例创建(如单例、类型检查、对象池)。

直接说结论: __new__ 是真正负责“分配内存并返回实例”的方法,它在 __init__ 之前执行;想拦截、复用、限制或定制实例创建(比如单例、类型检查、对象池),必须重写 __new__,而不是只靠 __init__。
为什么 __new__ 必须返回实例,否则会报错
__new__ 是静态方法,第一个参数是 cls,它要负责调用父类的 __new__(通常是 object.__new__(cls))来获得新对象。如果忘了 return,Python 默认返回 None,接着就会在初始化时抛出 TypeError: __init__() missing 1 required positional argument: 'self' —— 因为根本没实例可传给 __init__。
常见错误写法:
def __new__(cls, value):
print("分配前")
object.__new__(cls) # ❌ 忘了 return!
print("分配后")
正确写法:
def __new__(cls, value):
print("分配前")
instance = object.__new__(cls) # ✅ 显式赋值并返回
print("分配后")
return instance
- 即使你打算返回别的对象(比如缓存实例),也必须有
return - 不调用
object.__new__也能返回对象(例如返回已有实例),但不能什么都不返回 - 返回非
cls类型的实例时,__init__不会自动调用(Python 认为你已完全接管)
实现单例时,__new__ 的典型结构和易错点
单例是最常见的 __new__ 使用场景,核心是:只在第一次调用时新建实例,后续都返回同一个。
标准写法:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
class Singleton:
_instance = None
<pre class="brush:python;toolbar:false;">def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
容易踩的坑:
- 用
if not cls._instance:判断 —— 如果_instance被设为0、False或空列表,会被误判为未初始化 - 没加
super()或写成object.__new__(cls)—— 多继承时可能跳过中间父类的__new__,推荐统一用super().__new__(cls) - 在
__new__里调用了__init__—— 单例多次获取时,__init__会被反复执行,导致状态被重置;应确保__init__具备幂等性,或用标志位控制
用 __new__ 做类型预检或实例复用(比如整数缓存)
Python 内置的 int、str 等小值对象就用了类似逻辑:相同小整数总是同一对象。你可以模仿这种行为。
示例:限制只允许创建 -5 到 5 的整数实例,超出范围则抛异常:
class SafeInt:
_cache = {}
<pre class="brush:python;toolbar:false;">def __new__(cls, value):
if not isinstance(value, int):
raise TypeError("only int allowed")
if value 5:
raise ValueError("value must be between -5 and 5")
if value in cls._cache:
return cls._cache[value]
instance = super().__new__(cls)
instance._value = value
cls._cache[value] = instance
return instance
关键细节:
-
_cache必须是类属性(定义在类体里),不是实例属性,否则无意义 - 缓存的是完整实例,不是原始值;所以需要在
__new__中手动设置内部字段(如instance._value),因为__init__可能不被执行 - 这种模式不适合带可变状态的对象,因为复用实例等于复用状态
最常被忽略的一点:一旦重写了 __new__,就要同步考虑 __init__ 的执行时机和副作用——它不一定每次都被调用,也不一定只执行一次。控制权在你手上,但责任也在你手上。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










