Python中__new__与__init__的执行顺序及核心区别详解

程一诺
程一诺
发布时间:2026-10-12 | 1人浏览过
原创

本文详细解析Python中__new__与__init__两个特殊方法的执行顺序与核心区别。__new__作为类级别的静态方法,负责创建并返回实例对象;__init__作为实例级别的方法,负责初始化已创建的实例。通过继承int等不可变类的示例,展示如何重载__new__实现自定义实例化逻辑,帮助开发者理解对象创建机制。

相同点

两者均为Python面向对象体系中的内置函数。其中,__new__的使用频率相对较低,而__init__则是日常开发中更为常见的函数。

不同点

__new__在实例创建之前被调用,其核心任务是创建实例对象并返回该实例,因此它属于静态方法。相比之下,__init__在实例对象创建完成后被调用,主要用于设置对象属性的初始值,通常用于初始化类实例,属于实例方法。

简而言之:__new__先执行,__init__后执行。__new__的返回值(即创建的实例)会作为第一个参数传递给__init__方法,随后__init__利用该实例进行参数设置。

===》》》

补充说明

1、只有继承自object的新式类才具备__new__方法。

2、__new__至少需要包含一个参数cls,代表当前类。在实例化过程中,Python解释器会自动识别并传入该参数。

3、__new__必须包含返回值,即返回实例化后的实例。在自定义实现__new__时需特别注意:可以返回通过super(当前类名, cls)调用的父类__new__产生的实例,或者直接返回由object的__new__产生的实例。

4、__init__包含一个参数self,该参数即为__new__返回的实例。__init__在__new__的基础上完成其他初始化动作,且__init__不需要返回值。

5、如果__new__创建的是当前类的实例,系统会自动调用__init__函数。通过return语句中调用的__new__函数的第一个参数cls来确保是当前类实例;若返回的是其他类的类名,则实际创建并返回的是其他类的实例,此时不会调用当前类的__init__函数,也不会调用其他类的__init__函数。

6、在定义子类时,若未重新定义__new__(),Python默认会调用该类的直接父类的__new__()方法来构造该类的实例。如果该类的父类也未重写__new__(),则规则将一直追溯至object的__new__()方法,因为object是所有新式类的基类。

7、若子类中重写了__new__()方法,你可以自由选择任意其他新式类(必须为新式类,因为所有新式类都拥有__new__(),而经典类没有)的__new__()方法来制造实例。这包括该新式类的所有前代类和后代类,只要不造成递归死循环即可。注意:绝对不能调用自己的__new__,否则会导致死循环。

8、对于子类的__init__,其调用规则与__new__一致。若需同时调用子类和父类的__init__函数,可在子类的__init__函数中显式加入对父类__init__函数的调用。

9、在实际使用中,建议优先使用__init__函数,尽量避免自定义__new__函数,因为两者在继承派生时的特性存在显著差异。

10、可以将类比作制造商:__new__方法相当于前期的原材料采购环节,而__init__方法则是在拥有原材料的基础上,进行加工和初始化的商品制作环节。

__init__方法

__new__方法

__new__方法接受的参数虽然与__init__相似,但__init__是在类实例创建之后调用,而__new__方法正是用于创建该类的实例。

===》

具体的执行逻辑如下:

1. p = Person(name, age)

2. 首先执行使用name和age参数来调用Person类的__new__方法,该__new__方法会返回Person类的一个实例(通常情况下采用 super(Persion, cls).__new__(cls, ... ...) 的方式),

3. 随后利用该实例来调用类的__init__方法,上一步中__new__产生的实例即为__init__中的self。

因此,__init__和__new__最主要的区别在于:

1.__init__通常用于初始化一个新实例,控制初始化过程,例如添加属性或执行额外操作,发生在类实例创建完成之后。它是实例级别的方法。

2.__new__通常用于控制生成一个新实例的过程。它是类级别的方法。

__new__的作用

根据Python官方文档,__new__方法主要用于当你继承一些不可变的class(如int、str、tuple)时,提供自定义这些类实例化过程的途径。此外,它还用于实现自定义的metaclass。

首先来看第一个功能,我们可以以int为例进行具体说明:

假如我们需要一个永远为正数的整数类型,通过集成int,我们可能会写出如下代码。

但运行后会发现,结果并非预期,我们仍然得到了-3。这是因为对于int这类不可变对象,只有重载其__new__方法才能起到自定义作用。

这是修改后的代码:

通过重载__new__方法,我们成功实现了所需功能。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表