Class Factory
The most common application of a metaclass is as a class factory. When you call the class method to construct an object, Python calls the metaclass method to build a new class. When used in conjunction with the standard __init__ and __new__ methods, Metaclasses allow you to perform things like registering the new class with a registry or replacing it totally when creating a class.
Recommended Topic, Python Round Function and Convert String to List Python.
Metaclass __new__() and __init__() methods
- __new__(): Before __init__, a method named __new__() is invoked (). It generates and returns the object. This method can be overridden to modify how the objects are produced.
- __init__(): This method simply initializes the object created and supplied as a parameter.
You can implement the metaclass's __new__ or __init__ methods to aid in the construction and initialization of the class in the metaclass. The majority of real-world metaclasses will most likely override only one of them. The metaclass is similar to a class in that it has a __new__ method for creating a class instance and a __init__ method for customizing the instance. If you want to return something other than a freshly generated class of the type, you must use __new__.
Example
class MetaOne(type):
def __new__(cls, name, bases, dict):
pass
class MetaTwo(type):
def __init__(self, name, bases, dict):
pass
Also Read, Divmod in Python
Metaclass __call__() method
By implementing a custom __call__() method in the metaclass, we can override other class methods and perform a specific action when the class is invoked.
Example
class MetaClassUsingCall(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(MetaClassUsingCall,cls).__call__(*args, **kwargs)
return cls._instances[cls]
class RegularClass(metaclass=MetaClassUsingCall):
pass
Creating custom Metaclass
The fundamental purpose is to alter the class when it is created automatically. This is typically done in APIs when you wish to construct classes that match the current context. Your own metaclass must inherit type metaclass and usually override to be created.
For example, if we define a class ‘Calc’ with three methods and want to add functionality to debug all the methods in one class, we can use meta-class for this.
class Calc():
def add(self, x, y):
return x + y
def sub(self, x, y):
return x - y
def mul(self, x, y):
return x * y
def debugFunc(func):
def wrapper(*args, **kwargs):
print("{0} is called with parameters {1}".format(func.__qualname__, args[1:]))
return func(*args, **kwargs)
return wrapper
def debugAllFuncs(cls):
for key, val in vars(cls).items():
if callable(val):
setattr(cls, key, debugFunc(val))
return cls
class DebugClass(type):
def __new__(cls, clsname, bases, clsdict):
obj = super().__new__(cls, clsname, bases, clsdict)
obj = debugAllFuncs(obj)
return obj
class Calc(metaclass=DebugClass):
def add(self, x, y):
return x + y
def sub(self, x, y):
return x - y
def mul(self, x, y):
return x * y
calc = Calc()
print(calc.add(2, 3))
print(calc.sub(2, 3))
print(calc.mul(2, 3))
Output:
Calc.add is called with parameters (2, 3)
5
Calc.sub is called with parameters (2, 3)
-1
Calc.mul is called with parameters (2, 3)
6
In the above example, we created a metaclass and wrote a decorator function to print the invoked function and its parameters. ‘Calc’ is inherited from ‘MetaDebugClass’. Therefore, its methods were by default decorated by the decorator function.
This way, we have added additional functionality to all the existing functions in the class. We can use meta-classes to achieve more, such as adding a new function to the class and removing a function from the class.
You can compile it with online python compiler.
Also read, Python filename extensions
FAQs
What is a metaclass in Python?
A metaclass is a blueprint for the class as a whole, just as a class is a blueprint for its instances. It is used to define how a class behaves.
When do we use a metaclass?
When you need dynamic behaviour that can't be defined at the object level but can be defined at the class level, you'll have to rely on metaclasses.
What is the use of the __new__ method?
Before __init__, a method named __new__() is invoked (). It generates and returns the object. This method can be overridden to modify how the objects are produced.
Conclusion
In this article, we studied in detail metaclasses in python. We saw the use of __new__ and __init__ methods in metaclasses and implemented a metaclass to add the debug functionality to an existing class. We hope that this blog has helped you enhance your knowledge of metaclasses. Do upvote our blog to help other ninjas grow.
Also, visit our Guided Path in Coding Ninjas Studio to learn about such content. If you are preparing for an interview, visit our Interview Experience Section. To become more confident in DSA, try out Interview Problems in our Code studio. I wish you all the best for your coming adventures and Happy Coding.
Useful links: Operational Databases , Non- relational databases , MongoDB, Top-100-sql-problems , interview-experience, guided-paths