Module (73%)
Section (73%)

Now that we know what’s happening under Python's hood, it’s time to implement our own metaclass.

It’s important to remember that metaclasses are classes that are instantiated to get classes.

The first step is to define a metaclass that derives from the type type and arms the class with a 'custom_attribute', as follows:

class My_Meta(type): def __new__(mcs, name, bases, dictionary): obj = super().__new__(mcs, name, bases, dictionary) obj.custom_attribute = 'Added by My_Meta' return obj

Pay attention to the fact that:

  • the class My_Meta is derived from type. This makes our class a metaclass;
  • our own __new__ method has been defined. Its role is to call the __new__ method of the parent class to create a new class;
  • __new__ uses 'mcs' to refer to the class – it’s just a convention;
  • a class attribute is created additionally;
  • the class is returned.

Let's make use of the metaclass to create our own, domain-specific class, and check if it’s armed with the custom attribute:

class My_Object(metaclass=My_Meta): pass print(My_Object.__dict__)

Pay attention to the fact that:

  • a new class has been defined in a way where a custom metaclass is listed in the class definition as a metaclass. This is a way to tell Python to use My_Meta as a metaclass, not as an ordinary superclass;
  • we are printing the contents of the class __dict__ attribute to check if the custom attribute is present.
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'My_Object' objects>, '__weakref__': <attribute '__weakref__' of 'My_Object' objects>, '__doc__': None, 'custom_attribute': 'Added by My_Meta'}

output

Indeed, the class attribute has been created.

Congratulations! You have just examined you first metaclass!


Code

class My_Meta(type):
def __new__(mcs, name, bases, dictionary):
obj = super().__new__(mcs, name, bases, dictionary)
obj.custom_attribute = 'Added by My_Meta'
return obj

class My_Object(metaclass=My_Meta):
pass

print(My_Object.__dict__)
{{ dockerServerErrorMsg }} ×
{{ errorMsg }} ×
{{ successMsg }} ×