python之类的new和init
Python 核心概念总结: __new__ vs. __init__
一、核心职责:创建 与 初始化
简单来说,它们的关系可以概括为:
__new__(构造方法): 负责创建对象。它是一个 类方法,它的主要工作是申请内存空间,并返回一个该类的空白实例。__init__(初始化方法): 负责初始化对象。它是一个 实例方法,它的工作是在__new__创建好实例之后,对这个实例进行属性的赋值和其他初始化设置。
二、详细区别与执行流程
| 特性 | def __new__(cls, *args, **kwargs) |
def __init__(self, *args, **kwargs) |
|---|---|---|
| 作用 | 创建并返回一个实例对象 (instance) | 初始化这个已创建的实例对象 |
| 调用时机 | 在 __init__ 之前被自动调用 |
在 __new__ 成功返回一个实例后才被自动调用 |
| 第一个参数 | cls (代表当前的类) |
self (代表由 __new__ 创建并返回的那个实例) |
| 返回值 | 必须返回一个实例对象。通常通过 super().__new__(cls) 实现。 |
不应该有任何返回值 (或者说,隐式返回 None)。 |
| 使用场景 | 绝大多数情况无需重写。 | 几乎所有类都会重写它来设置初始属性。 |
调用流程
当执行 my_instance = MyClass(arg1, arg2) 时,Python 内部的步骤是:
- Python 调用
MyClass.__new__(MyClass, arg1, arg2)。 __new__方法(通常是继承自object的)创建一个MyClass的实例,我们称之为obj。__new__方法返回这个obj。- Python 检查返回的
obj。如果它确实是MyClass的一个实例,Python 就会自动调用__init__方法,并将obj作为第一个参数self传入:MyClass.__init__(obj, arg1, arg2)。 - 最后,
__new__创建的那个obj被赋值给my_instance。
三、为什么我们通常只写 __init__?
这是一个非常关键的问题。我们平时写的类几乎都只有 __init__ 方法,但它们依然能成功创建对象。
原因在于继承:
- 所有 Python 类,如果你不明确指定,都默认继承自最顶层的基类
object。 - 这个
object基类本身就已经实现了一个功能完备的__new__方法。 - 当你创建自己类的实例时,Python 会自动向上查找到并调用
object.__new__来为你完成实例的创建工作。
因此,你不需要自己去实现 __new__,因为你总是在免费使用 object 类提供的那个。
四、什么时候需要重写 __new__?
只有在你不想使用默认的对象创建流程,想要从根本上改变对象的创建方式时,才需要重写 __new__。主要有两种场景:
-
实现单例模式 (Singleton Pattern): 在
__new__中检查一个类级别的变量,如果实例已存在,就直接返回现有实例,而不是创建一个新的。 -
继承不可变类型 (Immutable Types): 当你继承像
int,str,tuple这样的不可变类型时,必须使用__new__。因为这些类型的实例在创建后就不能被修改,所有初始化的逻辑都必须在实例创建阶段(即__new__中)完成。
浙公网安备 33010602011771号