Search code examples
pythonmetaclass

Can you create classes without the type function?


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.


Solution

  • 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.