跳到主要内容

Python 的 __init__ 和 __new__ 方法有什么区别?

核心区别​

方法职责调用时机返回值
__new__创建实例(分配内存)在 __init__ 之前必须返回实例对象
__init__初始化实例(设置属性)在 __new__ 之后必须返回 None

执行顺序​

class MyClass:
def __new__(cls, *args, **kwargs):
print("1. __new__ 被调用 —— 创建实例")
instance = super().__new__(cls)
return instance

def __init__(self, value):
print("2. __init__ 被调用 —— 初始化实例")
self.value = value

obj = MyClass(42)
# 输出:
# 1. __new__ 被调用 —— 创建实例
# 2. __init__ 被调用 —— 初始化实例

关键细节​

__new__ 若不返回当前类的实例,则 __init__ 不会被调用:

class Weird:
def __new__(cls):
print("__new__ 执行")
return "not an instance" # 返回非实例

def __init__(self):
print("__init__ 执行") # 永远不会打印

obj = Weird()
print(obj) # "not an instance"
print(type(obj)) # <class 'str'>

典型应用场景​

1. 单例模式​

class Singleton:
_instance = None

def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance

a = Singleton()
b = Singleton()
print(a is b) # True

2. 继承不可变类型(如 int、str、tuple)​

不可变类型的值在创建时就确定,必须在 __new__ 中设置:

class PositiveInt(int):
def __new__(cls, value):
if value <= 0:
raise ValueError(f"值必须为正数,得到 {value}")
return super().__new__(cls, value)

n = PositiveInt(5) # 正常
n = PositiveInt(-1) # 抛出 ValueError

3. 元类(Metaclass)​

元类通过 __new__ 控制类的创建过程,而不是实例的创建。

总结​

  • 日常开发:只需重写 __init__,用于初始化对象属性。
  • 需要控制实例创建本身(单例、不可变类型继承、元类)时,才重写 __new__。
  • 两者配合:__new__ 负责"生孩子",__init__ 负责"养孩子"。