在CPython中用C语言实现的类型实际上是类型树的一部分

72 阅读2分钟

在 Python 中,理论上所有的类型都是从object 下来的 (它们是它的直接或间接子类)。多年来,我一直认为 (并写道) 在 CPython (Python 的标准实现,你可能正在使用) 中用本地 C 代码编写的类型,在实现层面上不是这样的。用 C 语言编写的类型可能会表现得好像它们是从object 下来的,但我认为它们的行为实际上是完全独立的,由每个类型在 C 语言中分别实现。由Python 幕后花絮 #6:Python 对象系统是如何工作的,我发现我错了。

在 CPython 中,C 级 Python 类型并不是 C 级版本object 的字面意义上的子类,因为 C 当然没有那种意义上的类和子类。相反,你通常通过为你的类型定义一个 PyTypeObject结构来描述你的类型,其中有各种各样的字段,你可以根据需要填入或不填入,包括一个 tp_base字段(如果你想要一个以上的基类型,你需要采取堆类型的另一种方式)。当CPython需要对你的类型执行特殊方法或其他操作时,它将直接使用你的PyTypeObject结构上的字段(而且据我所知,它只使用这些字段,没有回退)。从表面上看,这看起来tp_base 字段基本上是装饰性的,只是在人们问起时用来报告你声称的__base__

然而,有一点CPython的魔力隐藏在幕后。 为了真正使用一个PyTypeObject 作为一个类型,你必须注册它,并使它准备好通过调用 PyType_Ready.作为其中的一部分,PyType_Ready 将使用你的类型的tp_base 来填充你的PyTypeObject 的各种字段,如果你还没有这样做的话,这实际上意味着你的C级类型将从其基本类型继承这些字段(以此类推,一直到object )。这在C API 的一个章节中有所概述,当然我自己从来没有读过 C API,因为我从来不需要使用它。 如果你好奇的话,[the] Python 对象系统是如何工作的这篇文章有更多细节,还有关于特殊方法如何工作的细节 (这比我的想法更有趣,而且我以前也看过这个领域)。

(repr() ,什么被认为是 "类型",什么被认为是 "类 "之间的区别有些武断;见这里的侧边栏。用PyTypeObject 定义的C级事物可能总是被认为是类型而不是类)。