在 Python 3 中,__new__ 和 __init__ 都是对象创建过程中的特殊方法(魔术方法),但它们的职责、调用时机和用途完全不同。理解它们的区别对掌握 Python 面向对象机制非常重要。


一、核心区别概览

特性__new____init__
作用创建对象实例(分配内存)初始化对象(设置属性)
调用时机在对象创建时最先调用在 __new__ 返回实例后调用
返回值必须返回一个实例(通常是 cls 的实例)不返回任何值(应返回 None
是否可省略通常不需要自定义(除非控制实例创建)通常需要自定义来初始化属性
类方法 or 实例方法静态方法(实际是类方法,第一个参数是 cls实例方法(第一个参数是 self

二、详细说明

1. __new__:负责“造”对象

  • 真正的构造器(constructor),负责创建并返回一个新的实例。
  • 签名通常是:
    def __new__(cls, *args, **kwargs):
        # 创建实例
        instance = super().__new__(cls)
        return instance  # 必须返回一个实例
  • 如果 __new__ 没有返回 cls 的实例,则 __init__ 不会被调用
  • 常用于:
    • 实现单例模式
    • 控制实例创建(如返回缓存对象)
    • 不可变类型(如 intstrtuple)的子类化

✅ 示例:自定义 __new__

class Person:
    def __new__(cls, name, age):
        print("1. __new__ 被调用")
        instance = super().__new__(cls)  # 创建实例
        return instance  # 返回实例

    def __init__(self, name, age):
        print("2. __init__ 被调用")
        self.name = name
        self.age = age

p = Person("Alice", 30)
# 输出:
# 1. __new__ 被调用
# 2. __init__ 被调用

2. __init__:负责“装”对象

  • 初始化器(initializer),负责给已创建的实例设置初始状态(如属性赋值)。
  • 不创建对象,只在对象已经存在后运行。
  • 不能有返回值(如果写了 return 且不是 None,会报错)。

✅ 示例:__init__ 不能返回值

class BadExample:
    def __init__(self):
        return "hello"  # ❌ TypeError: __init__ should return None

# BadExample() 会报错

三、关键行为:__new__ 决定是否调用 __init__

class Demo:
    def __new__(cls):
        print("__new__ called")
        # 不返回 cls 的实例!
        return "Not an instance"

    def __init__(self):
        print("__init__ called")  # ❌ 这行永远不会执行!

obj = Demo()
print(obj)  # 输出: Not an instance
# 注意:obj 不是 Demo 的实例!
print(type(obj))  # <class 'str'>

✅ 只有当 __new__ 返回的是 当前类(或其子类)的实例 时,Python 才会自动调用 __init__


四、典型应用场景

场景1:实现单例模式(Singleton)

class Singleton:
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance  # 总是返回同一个实例

s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True

场景2:继承不可变类型(如 int

class PositiveInt(int):
    def __new__(cls, value):
        if value < 0:
            value = 0
        return super().__new__(cls, value)

x = PositiveInt(-5)
print(x)  # 0 (因为 int 是不可变的,必须在 __new__ 中处理)

💡 对于不可变类型(strinttuple 等),必须在 __new__ 中完成“初始化”,因为 __init__ 无法修改已创建的实例。


五、总结口诀

  • __new__ 负责“生”(创建实例)
  • __init__ 负责“养”(初始化属性)
  • 先 __new__,后 __init__
  • __new__ 返回啥,__init__ 才有机会干活
  • 普通类一般只写 __init__;特殊需求才动 __new__

✅ 绝大多数情况下,你只需要重写 __init__。只有当你需要控制对象的创建过程(如单例、元类、不可变对象等)时,才需要自定义 __new__

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐