Mechanism

  1. __prepare__ is first called to prepare the default attributes,
  2. Python then scans each method definition and creates adds to this default attributes (including things like __name__, __module__ and __qualname__
  3. A new class is then constructed using __new__
  4. 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.

Resources