为什么 PyTypeObject 有这么多特定的成员来实现特定的功能

Why PyTypeObject has so many specific members for specific functionality

例如,PyFloat_Typetp_as_number中有很多操作。当这个类型对象被初始化时,所有这些操作将被写入它的 tp_dict 中,并带有插槽。

另一方面,当我编写自定义 class 并在其中包含 __add__ 时,它的 tp_dict 将包含 __add__。这个__add__函数会在类型对象初始化的时候被写入到带槽类型对象的tp_as_number中。

我想tp_dict已经记录了我们需要的所有信息。为什么我们需要 tp_as_number 等其他成员?这只是一个历史问题吗?

因为当 C 级函数正在使用您的类型时,它不会在 tp_dict 中按名称执行查找(慢),而是直接从 tp_as_number 中提取指针(快)。

几个指针取消引用是一个微不足道的成本,不需要引用计数样板等;大多数情况下,成本以个位数周期来衡量,其中 dict 查找的成本要高几个数量级左右。

常见的情况实际上是tp_as_numbersince a + b will actually use tp_as_number (or tp_as_sequence)知道它与tp_dict中的等效条目同步;如果简单的加法需要 dict 查找,CPython 会比现在慢得多。