Python __init__ 和 __new__ 的区别
FreeGuideOnline
9阅读
2026-07-05
python class MyClass: def new(cls, *args, **kwargs): # 必须返回一个实例,通常是 cls 的实例 instance = super().new(cls) return instance
- 第一个参数 `cls` 代表类本身。
- 必须返回一个对象实例,通常是通过调用父类的 `__new__(cls)` 创建的。
- 如果不返回 `cls` 的实例,`__init__` 将**不会被调用**。
- 主要用于控制不可变类型(如 `int`, `str`, `tuple`)的实例化,或实现单例模式等高级设计模式。
## 什么是 __init__ 方法?
`__init__` 是一个**实例方法**,在 `__new__` 成功返回实例后自动调用,负责**初始化**新创建的对象。它不返回任何值(必须返回 `None`)。
### __init__ 的签名与作用
```python
class MyClass:
def __init__(self, value):
self.value = value # 为实例添加属性
- 第一个参数
self是__new__刚刚创建出来的实例。 - 主要功能是设置对象的初始状态,如绑定属性、执行其他初始化逻辑。
- 不应该返回除
None以外的任何值,否则会引发TypeError。
执行顺序与协作流程
当执行 obj = MyClass(arg) 时,Python 内部依次进行如下操作:
- 调用
__new__:MyClass.__new__(MyClass, arg)被调用,必须返回一个实例对象。 - 检查返回值:如果返回值是
MyClass的实例,则继续下一步;否则跳过__init__。 - 调用
__init__:以该实例作为self,调用__init__(self, arg)完成初始化。 - 返回实例:最终将实例赋值给变量
obj。
可以用一个简单的例子验证顺序:
class Demo:
def __new__(cls, *args, **kwargs):
print("1. __new__ 被调用")
return super().__new__(cls)
def __init__(self):
print("2. __init__ 被调用")
demo = Demo() # 输出顺序:1,2
关键区别对比
| 特性 | new | init |
|---|---|---|
| 调用时机 | 实例创建时最先被调用 | 在 new 返回实例之后调用 |
| 作用 | 创建并返回实例 | 初始化已创建的实例 |
| 第一个参数 | cls(类本身) |
self(实例本身) |
| 返回值 | 必须返回一个对象实例 | 必须返回 None(隐式) |
| 是否必需 | 很少需要重写 | 经常重写 |
| 典型场景 | 继承不可变类型、单例模式 | 设置对象初始属性 |
何时需要自定义 new?
大多数情况下我们只需要重写 __init__,但在以下场景中必须重写 __new__:
- 子类化不可变类型(如
str、int、tuple):因为它们在创建后无法通过__init__修改值。 - 实现单例模式:确保一个类只有一个实例。
- 元编程:动态改变类的实例化行为。
单例模式实例
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, value):
# 注意:每次“构造”都会执行 __init__,可能覆盖已有属性,
# 需谨慎处理(这里仅作演示)
self.value = value
a = Singleton("first")
b = Singleton("second")
print(a is b) # True,同一个实例
print(a.value) # "second"(被重新初始化)