[Python3高阶编程] - __new__ 和 __init__ 的区别
·
在 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__不会被调用! - 常用于:
- 实现单例模式
- 控制实例创建(如返回缓存对象)
- 不可变类型(如
int,str,tuple)的子类化
✅ 示例:自定义 __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__ 中处理)
💡 对于不可变类型(
str,int,tuple等),必须在__new__中完成“初始化”,因为__init__无法修改已创建的实例。
五、总结口诀
__new__负责“生”(创建实例)__init__负责“养”(初始化属性)- 先
__new__,后__init____new__返回啥,__init__才有机会干活- 普通类一般只写
__init__;特殊需求才动__new__
✅ 绝大多数情况下,你只需要重写 __init__。只有当你需要控制对象的创建过程(如单例、元类、不可变对象等)时,才需要自定义 __new__。
更多推荐



所有评论(0)