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_Metais derived fromtype. 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_Metaas 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 }}
×