元类: Python创建示例的过程。
已于 2025年11月10日 14:04 修改
访问次数:0
我们来深入剖析 Python 对象创建机制:
当你写下 obj = MyClass(args) 时,Python 在底层到底做了哪些事情。
我们将以 CPython(Python 的官方实现) 的对象模型为蓝本,逐条讲清楚每个阶段的执行过程。
🧩 一、从表达式开始:obj = MyClass(args)
这行代码在 Python 解释器内部,触发以下调用:
obj = MyClass(*args, **kwargs)
相当于执行:
obj = MyClass.__call__(*args, **kwargs)
也就是说,类实例化时是通过 __call__ 实现的。
这点非常关键。
⚙️ 二、类的 __call__ 方法由元类(metaclass)提供
Python 中“一切皆对象”,包括类本身。
类对象是由它的元类(默认是 type)创建的,而 type 定义了 __call__:
type.__call__(cls, *args, **kwargs)
当你执行 MyClass(),其实就是执行:
type.__call__(MyClass, *args, **kwargs)
🧠 三、type.__call__ 的底层执行流程(关键!)
这是最核心的机制。
其内部逻辑大致等价于下面的伪代码(来自 CPython 源码简化版):
def type.__call__(cls, *args, **kwargs):
# 1️⃣ 调用 __new__ 创建实例
obj = cls.__new__(cls, *args, **kwargs)
# 如果 __new__ 没返回该类实例(例如返回了别的对象),
# 那么 __init__ 就不会被调用
if isinstance(obj, cls):
# 2️⃣ 调用 __init__ 初始化对象
cls.__init__(obj, *args, **kwargs)
# 3️⃣ 返回最终的对象
return obj
这就是 Python 创建实例的完整逻辑。
🧩 四、逐步展开执行过程(详细解剖)
假设我们有:
class MyClass:
def __new__(cls, *args, **kwargs):
print("Step 1: __new__ called")
instance = super().__new__(cls)
print("Step 2: __new__ returns instance", instance)
return instance
def __init__(self, x):
print("Step 3: __init__ called")
self.x = x
print("Step 4: x =", self.x)
obj = MyClass(42)
我们来按 解释器执行顺序 拆解每一步:
🔹 Step 0:元类准备阶段
当解释器读取 class MyClass: 时,实际上执行:
MyClass = type("MyClass", (object,), {...})
于是:
- 创建了类对象 MyClass
- 它的元类是 type
- MyClass.__call__ = type.__call__
🔹 Step 1:调用 type.__call__
执行 MyClass(42) 时,相当于:
type.__call__(MyClass, 42)
进入 type.__call__ 内部逻辑:
🔹 Step 2:执行 MyClass.__new__(MyClass, 42)
Python 会查找类定义中的 __new__ 方法:
obj = MyClass.__new__(MyClass, 42)
此时:
- 参数 cls = MyClass
- 返回值必须是某个对象(通常是 MyClass 的实例)
super().__new__(cls) 实际调用的是 object.__new__(cls),它会:
- 在堆上为新对象分配内存
- 创建一个空对象(未初始化)
🔹 Step 3:返回对象引用
__new__ 返回刚刚创建的对象引用,交给 type.__call__。
🔹 Step 4:判断返回类型
type.__call__ 检查返回值:
if isinstance(obj, cls):
cls.__init__(obj, *args, **kwargs)
如果 obj 是 MyClass 的实例,就执行下一步。
(⚠️ 如果 __new__ 返回了别的类型,比如 str 或 None,__init__ 就不会被执行。)
🔹 Step 5:执行 __init__
Python 调用:
MyClass.__init__(obj, 42)
此时:
- self = obj,即刚刚 __new__ 创建的对象
- __init__ 往对象里设置属性、状态
🔹 Step 6:返回最终对象
__init__ 总是返回 None。
最后,type.__call__ 返回 obj,赋值给变量。
此时:
obj = <MyClass instance with x=42>
🧩 五、对象生命周期图(完整流程)
┌──────────────────────────────┐
│ MyClass() │
└────────────┬────────────────┘
│
▼
type.__call__(cls, *args)
│
┌───────┴─────────────┐
▼ ▼
cls.__new__(cls, *args) (创建实例)
│
▼
返回对象实例
│
▼
if isinstance(obj, cls):
cls.__init__(obj, *args)
│
▼
返回最终实例对象
🧠 六、__new__ 与内存层的关系
- __new__ 负责分配内存(创建对象) → 它调用 object.__new__(cls),底层会申请内存块并初始化基本结构。
- __init__ 负责在已有内存中初始化数据 → 即对对象的属性表(__dict__)进行赋值操作。
换句话说:
| 阶段 | 类似于C语言中的过程 |
|---|---|
__new__ | malloc()(分配内存) |
__init__ | “构造函数”(初始化内存) |
🧱 七、验证:__new__ 先于 __init__ 执行
class A:
def __new__(cls):
print("A.__new__")
instance = super().__new__(cls)
print("A.__new__ end")
return instance
def __init__(self):
print("A.__init__")
A()
输出:
A.__new__
A.__new__ end
A.__init__
🧠 八、特殊情况:__new__ 返回别的类型
class Weird:
def __new__(cls):
print("Weird.__new__")
return "I'm not an instance"
def __init__(self):
print("Weird.__init__")
obj = Weird()
print(obj)
输出:
Weird.__new__
I'm not an instance
说明:
- __init__ 不执行;
- 因为 __new__ 返回了字符串,而不是 Weird 的实例。
✅ 九、总结表格
| 阶段 | 函数 | 主要任务 | 调用者 | 是否必须返回 |
|---|---|---|---|---|
| 1️⃣ | __new__(cls, *args) | 创建对象(分配内存) | 由 type.__call__ 调用 | ✅ 必须返回对象 |
| 2️⃣ | __init__(self, *args) | 初始化对象(赋值) | 由 type.__call__ 调用 | ❌ 必须返回 None |
| 3️⃣ | __call__ | 统筹调用两者 | 元类 (type) | ✅ 返回实例 |
🎯 十、总结一句话(面试或笔记记法)
“__new__ 造胚子,__init__ 填内容,二者由 type.__call__ 串联。”
评论(0)