For example, the PyFloat_Type has many operations in tp_as_number. When this type object gets initialized, all these operations will be written into tp_dict of it with slots.
On the other hand, when I write a custom class with __add__ in it, it's tp_dict will have __add__. This __add__ function will be written into tp_as_number of the type object with slots when the type object gets initialized.
I think tp_dict has recorded all the information we need. Why do we need other members such as tp_as_number? Is this just a historical issue?