__prepare__ is first called to prepare the default attributes,
Python then scans each method definition and creates adds to this default attributes (including things like __name__, __module__ and __qualname__
A new class is then constructed using __new__
The new class is initialized using __init__ in the metaclass
Additional Learnings
Usually one will use __new__ to modify behaviour, as __init__ only contains a subset of __new__’s functionality
It cannot modify an already created instance (i.e. class)
Metamethods (i.e. methods to the metaclass definition) are only accessible by the meta class and class, but not by the class instance
__prepare__ has to be decorated with @classmethod
The first argument to each of these special methods are as follows:
__prepare__: mcs since it is already decorated with @classmethod
__new__: mcs (even though there’s no @classmethod)
__init__: cls (i.e. the class instantiated by __new__)
When overriding any of these methods, don’t forget to call upon the superclass’s (i.e. type) implementation
Metaclass variables are copied to each class. That way, each class of Metaclasses do not share the same metaclass variable
Methods can be injected in __new__ or __prepare__. Injecting them in __prepare__ allows for (nonexistent) class decorators to be used, because those class decorators are defined in Step 1, before being seen in Step 2.