在 Python 中,__new__ 和 __init__ 都是与对象创建相关的特殊方法,但它们的作用和调用时机截然不同。简单来说:__new__ 负责创建实例,__init__ 负责初始化实例。
核心区别对比
| 特性 | __new__ | __init__ |
|---|---|---|
| 作用 | 创建类的实例对象(分配内存) | 初始化已创建的实例(设置属性等) |
| 调用时机 | 实例创建前被调用 | 实例创建后(__new__ 返回实例后)被调用 |
| 参数 | 第一个参数是 cls(类本身) | 第一个参数是 self(刚创建的实例) |
| 返回值 | 必须返回一个实例对象(通常是当前类) | 无返回值(若返回非 None 会报错) |
| 方法类型 | 类方法(隐式被 @classmethod 修饰) | 实例方法 |
| 是否必须实现 | 非必须(默认调用父类的 __new__) | 非必须(无自定义初始化逻辑时可省略) |
详细解析
1. __new__:创建实例的 “构造器”
__new__ 是 Python 中真正负责创建实例对象的方法。当你调用 ClassName() 创建实例时,Python 会先调用 __new__ 方法,为对象分配内存并返回一个实例。
- 参数:第一个参数是
cls(表示当前类),后续参数与类的构造参数一致。 - 返回值:必须返回一个实例(通常是通过
super().__new__(cls)调用父类的__new__来创建)。如果__new__没有返回实例,__init__不会被调用。
示例:
python
运行
class MyClass:
def __new__(cls, *args, **kwargs):
print("__new__ 被调用,创建实例")
# 调用父类的__new__创建并返回实例
instance = super().__new__(cls)
return instance
def __init__(self, name):
print("__init__ 被调用,初始化实例")
self.name = name
# 创建实例
obj = MyClass("test")
# 输出:
# __new__ 被调用,创建实例
# __init__ 被调用,初始化实例
2. __init__:初始化实例的 “初始化器”
__init__ 是在 __new__ 成功创建实例后被调用的方法,用于初始化实例的属性(如设置初始值、绑定方法等)。它不负责创建实例,而是 “修饰” 已存在的实例。
- 参数:第一个参数是
self(即__new__返回的实例),后续参数与类的构造参数一致。 - 返回值:必须为
None(若返回其他值会抛出TypeError)。
示例:
python
运行
class Person:
def __init__(self, name, age):
# 初始化实例属性
self.name = name
self.age = age
p = Person("Alice", 30)
print(p.name) # 输出:Alice(__init__ 初始化的属性)
典型使用场景
__new__ 的常见用途:
-
子类化不可变类型:如
int、str、tuple等不可变类型,由于它们创建后无法修改,需在__new__中定制实例(__init__无法做到)。python
运行
class PositiveInt(int): def __new__(cls, value): # 确保创建的int实例是正数 return super().__new__(cls, abs(value)) num = PositiveInt(-5) print(num) # 输出:5(通过__new__修改了初始值) -
实现单例模式:控制类只能创建一个实例(每次调用类时返回同一个实例)。
python
运行
class Singleton: _instance = None # 保存唯一实例 def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance a = Singleton() b = Singleton() print(a is b) # 输出:True(a和b是同一个实例)
__init__ 的常见用途:
- 为实例设置初始属性(最常用场景)。
- 执行实例创建后的初始化逻辑(如连接数据库、加载配置等)。
总结
__new__是 “创建者”,负责实例的诞生(分配内存、返回实例)。__init__是 “化妆师”,负责实例的初始化(设置属性、初始化状态)。- 两者协同完成对象的创建流程:
__new__先创建实例,__init__再初始化它。
日常开发中,__init__ 使用率远高于 __new__,只有在需要控制实例创建过程(如不可变类型子类化、单例等)时,才需要重写 __new__。
3859

被折叠的 条评论
为什么被折叠?



