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 内部依次进行如下操作:

  1. 调用 __new__MyClass.__new__(MyClass, arg) 被调用,必须返回一个实例对象。
  2. 检查返回值:如果返回值是 MyClass 的实例,则继续下一步;否则跳过 __init__
  3. 调用 __init__:以该实例作为 self,调用 __init__(self, arg) 完成初始化。
  4. 返回实例:最终将实例赋值给变量 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__

  • 子类化不可变类型(如 strinttuple):因为它们在创建后无法通过 __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"(被重新初始化)