OfirD
OfirD

Reputation: 10460

where does a user-defined type's metaclass' __new__ and __init__ get invoked?

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

Answers (2)

abarnert
abarnert

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

user2357112
user2357112

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

Related Questions