Search code examples
pythontypescpythonlanguage-implementation

When a user-defined type is called, what causes tp_new to reference object_new?


When a user-defined type is called to create a new object, type_call is called. Its first parameter is PyObject *type. Then, type->tp_new is called to create the object.

I'm reading Eli Bendersky's article (And following along CPyton's source code) where it is explained that in such case, calling tp_new invokes object_new. Here's how it works (Joe is a user-defined type; Italic is added):

Since the type parameter passed to type_call in our case is Joe, and Joe does not define a custom __new__ method, then type->tp_new defers to the tp_new slot of the base type.

The base type of Joe [...] is object. The object.tp_new slot is implemented in CPython by the object_new function in Objects/typeobject.c.

So, if I understand this correctly, it follows that if type->tp_new references object_new, then the runtime type of type must be PyBaseObject_Type* (Because only PyBaseObject_Type.tp_new references object_new).

My question: What are the steps - preceding the invocation of type_call - that makes type point to a PyBaseObject_Type variable?


Solution

  • You've misunderstood how things work. During setup of a user-defined class, if the class doesn't define its own __new__, its tp_new is copied from the "dominant base". You can see the code for this in inherit_special:

        if (base != &PyBaseObject_Type ||
            (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
            if (type->tp_new == NULL)
                type->tp_new = base->tp_new;
        }
    

    There is no need for the class itself to be PyBaseObject_Type, or "a PyBaseObject_Type variable".