Reputation: 10460
I'm reading several articles to understand how class types are created in Python (1, 2, 3), and following along Python's source code (typeobject.c).
My Question: When a new user-defined type is created, where does its metaclass' __new__
and __init__
get invoked?
I'll explain:
say we have a simple user-defined type:
class A(object): pass
To create the type A
, type_call
is eventually invoked, with type
as its first parameter. In this case, type
is actually PyType_Type
.
Inside type_call
, tp_new
is called, which in this case means a call to type_new
.
Now, Inside type_new
, the new type is eventually allocated with:
/* Allocate the type object */
type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
And when type_new
finishes, it returns type
to type_call
. Then, type_call
calls tp_init
- which means a call to type_init
, which invokes object_init
, that doesn't really do anything.
Somewhere, type
's __new__
and __init__
should be called. Did I miss these calls along the way, or are they called outside type_call
?
Upvotes: 1
Views: 146
Reputation: 365707
As user2357112's answer explains, tp_new
is the type slot method, and the default version of it for Python-defined classes looks up and calls the __new__
method.
The idea of type slot methods isn't really explained all in a single place, but see Type Objects in the C API and New Types in the Extending and Embedding docs.
You'll also want to read the specific entries on tp_new
in both of those chapters, because it's a particularly special function.
If you want to see the source, most of the relevant stuff is in typeobject.c
. Notice that the __new__
wrapper is different from other Python method wrappers, and the name lookup doesn't call the generic special method lookup code, but the basics are still pretty similar.
Upvotes: 1
Reputation: 280465
tp_new
and tp_init
are the C-level counterparts of __new__
and __init__
. The calls to tp_new
and tp_init
are the __new__
and __init__
calls.
If you override type.__new__
or type.__init__
in a metaclass you define, the corresponding tp_new
or tp_init
slots in your metaclass will be set to C-level functions that search for and invoke your Python-level overrides.
Upvotes: 2