元类: Python创建示例的过程。

我们来深入剖析 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)

如果 objMyClass 的实例,就执行下一步。

(⚠️ 如果 __new__ 返回了别的类型,比如 strNone__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)