在Python面向对象编程体系中,__new__和__init__都是类中用于对象创建的特殊方法,但二者的定位和作用存在本质区别,理解它们的差异是掌握Python对象实例化流程的关键。

执行顺序差异
对象实例化的过程中,__new__方法会先于__init__方法执行。__new__负责创建对象实例,而__init__负责对已经创建好的实例进行初始化赋值。
我们可以通过简单的打印日志验证执行顺序:
class Demo:
def __new__(cls, *args, **kwargs):
print("执行__new__方法")
# 调用父类的__new__方法创建实例
return super().__new__(cls)
def __init__(self, value):
print("执行__init__方法")
self.value = value
# 实例化对象
obj = Demo(10)
运行上述代码后,输出结果会先显示执行__new__方法,再显示执行__init__方法,直观体现了两者的执行先后关系。
返回值的区别
__new__方法必须返回一个实例对象,这个对象就是后续会被__init__处理的实例。如果__new__没有返回有效实例,__init__方法不会被调用。
而__init__方法不需要返回值,它的职责是初始化实例的属性,即使返回了内容也不会被Python解释器处理。
下面的示例展示了__new__不返回实例时的情况:
class Demo2:
def __new__(cls, *args, **kwargs):
print("__new__执行,但没有返回实例")
# 没有返回实例
def __init__(self, value):
print("__init__执行")
self.value = value
obj2 = Demo2(20)
运行代码后只会打印__new__相关的输出,__init__方法不会被执行,因为__new__没有返回有效实例。
参数与重写场景差异
__new__方法的第一个参数是cls,代表当前类本身,通常用于返回类的实例;__init__方法的第一个参数是self,代表已经创建好的实例对象。
重写__new__的常见场景是实现单例模式、不可变类型(如int、str)的自定义子类等,而重写__init__的场景更多是对实例属性进行初始化赋值。
以下是用__new__实现单例模式的示例:
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, name):
self.name = name
s1 = Singleton("a")
s2 = Singleton("b")
# 两个实例是同一个对象
print(s1 is s2) # 输出True
print(s1.name) # 输出b,因为两次实例化都是同一个对象,后初始化的属性会覆盖之前的
核心差异总结
我们可以通过表格更清晰地对比两者的核心差异:
| 对比维度 | __new__方法 | __init__方法 |
|---|---|---|
| 执行顺序 | 先执行 | 后执行 |
| 核心职责 | 创建对象实例 | 初始化实例属性 |
| 返回值要求 | 必须返回实例对象 | 无返回值要求 |
| 第一个参数 | cls(类本身) | self(已创建的实例) |
| 典型重写场景 | 单例模式、不可变类型子类 | 实例属性初始化 |
总的来说,__new__是对象创建阶段的入口,__init__是对象初始化阶段的入口,二者配合完成了Python对象的实例化流程,在需要自定义对象创建逻辑时,优先考虑重写__new__,常规属性初始化则重写__init__即可。