This is a question for deeper understanding, I understand that in practice, use cases for something like this would be extremely rare (though by all means I'm eager to hear of them).
If I understand correctly, the default metaclass used to generate all classes is the type(..., ..., ...)
constructor function. In all examples I've seen of using custom metaclasses, at some point you are still calling the type(..., ..., ...)
constructor function as well. You might be returning a pre-existing value, but still you at some point called type
or one of the built-in classes to produce what you return.
Is this always the case? Is there a way to use this feature where you don't use type
at some point? Are there alternate methods to producing classes? Python seems to almost-always have some sort of well-actually-there's-a-protocol trick under the sheets.
Without calling the type "function" (it is actually a class), yes.
Without calling, at some step the type.__new__
method, no.
Not in pure Python code - it would be possible with a native code extension, that would re-use the data structures of Python itself. I'd not recommend trying it, but for playing around.
The formal way for doing it without calling type
is to use types.new_class
. It will,however, call type.__new__
internally.
BTW, for creating any instance of any class, with Python code, it is just the same with one of the built-in types .__new__
. Usually object.__new__
is needed, unless you subclass one of the other built-ins (int, float, list, dict) - some of those will bypass object.__new__
and instantiate the your subclass directly - but they can only do that using native code and manipulating the structures that represent an object directly.
ok, both things should be possible with ctypes, which allow you to manipulate the memory structures in "raw" and call the internal APIs. And therefore in "pure Python" - but the idea is the same: you have to redo the workings of object.__new__
or typing.__new__
and correctly populate the data structures that represent these objects. That would be way more cumbersome than doing the same from a C file.