You might have heard these thousands of time that everything in python is an object. For example,
>>> type(4)
<class 'int'>
>>> type('y')
<class 'str'>
As seen above, even basic types like integers and strings are objects. Since everything is an object and object is an instance of a class, then what is a class?
Let's see this in details,
>>> type(int)
<class 'type'>
>>> type(str)
<class 'type'>
Ironically, the class is an object too. They're the instance of the 'type' class or they're the instance of the type 'metaclass'.
Now, let's see what is metaclass.
A metaclass is responsible for the generation of classes, so we can write our own custom metaclasses to modify the way classes are generated by performing extra actions or injecting code. Usually, this is not necessary always.
Lets see a specific usage of a metaclass.
There are two modules, one is library.py and the other is user.py As a developer of the library, you have access to library.py but not to user.py
library.py
class Base:
def foo(self):
print(self.bar())
user.py
from framework import Base
class Derived(Base):
def bar(self):
print("bar")
Observe closely that the foo method in Base class requires bar method from Derived class. That means the User module has to write bar() method. But the problem here is, as a developer, you do not have access to view or edit user.py The question is, how do you force the developer of user.py to define bar() method?
change your library.py to this and see the magic.
class MetaClass(type):
def __new__(cls, name, base, body):
if not 'bar' in body:
raise TypeError("bad class, missing mandatory method bar.")
return super().__new__(cls, name, base, body)
class Base(metaclass=MetaClass):
def foo(self):
print(self.bar())
Here before before creating a Derived class, we are inserting pre checks to see if this class has bar() method.