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 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_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 }}
×