用户定义类型的元类 __new__ 和 __init__ 在哪里被调用?

where does a user-defined type's metaclass' __new__ and __init__ get invoked?

我正在阅读几篇文章以了解如何在 Python (1, 2, 3), and following along Python's source code (typeobject.c) 中创建 class 类型。

我的问题:创建新的用户定义类型时,它的元class' __new____init__ 在哪里被调用?

我来解释一下:

假设我们有一个简单的用户定义类型:

class A(object): pass

要创建类型 A,最终会调用 type_call,并将 type 作为其第一个参数。在这种情况下,type 实际上是 PyType_Type

type_call中,调用了tp_new,在本例中意味着调用type_new

现在,在 type_new 中,新类型最终分配为:

/* Allocate the type object */
type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);

type_new 完成时,它 returns typetype_call。然后,type_call 调用 tp_init - 这意味着调用 type_init,它调用 object_init,实际上并没有做任何事情。

在某处,type__new____init__ 应该被调用。我是不是错过了一路上的这些电话,还是他们在type_call外面打来的?

tp_newtp_init__new____init__ 的 C-level 对应项。对 tp_newtp_init 的调用是 __new____init__ 调用。

如果您在您定义的元类中覆盖 type.__new__type.__init__,则元类中相应的 tp_newtp_init 插槽将设置为 C-level functions 搜索并调用您的 Python-level 覆盖。

正如 所解释的那样,tp_new 是类型插槽方法,Python-defined 类 的默认版本查找并调用 __new__方法。

类型槽方法的概念并没有在一个地方得到真正的解释,但请参阅扩展和嵌入文档中的Type Objects in the C API and New Types

您还需要阅读这两章中关于 tp_new 的具体条目,因为这是一个特别特殊的功能。

如果你想看源码,大部分相关的东西都在typeobject.c。请注意,__new__ 包装器与其他 Python 方法包装器不同,名称查找不会调用通用的特殊方法查找代码,但基础仍然非常相似。