__new__和__init__的区别是什么

在 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__ 的常见用途:
  • 子类化不可变类型:如 intstrtuple 等不可变类型,由于它们创建后无法修改,需在 __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__

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值