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__负责"养孩子"。