Table of contents
1.
Introduction
2.
Metaclasses in python
3.
Class Factory
4.
Metaclass __new__() and __init__() methods
5.
Metaclass __call__() method
6.
Creating custom Metaclass
7.
FAQs
7.1.
What is a metaclass in Python?
7.2.
When do we use a metaclass?
7.3.
What is the use of the __new__ method?
8.
Conclusion
Last Updated: Mar 27, 2024
Easy

Class Metaprogramming

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Python is an object-oriented programming language that makes dealing with classes easy. In Python, a class is used to express a particular behaviour for its instances, which are Python objects. The class serves as the blueprint for the creation of these objects. In Python, a metaclass is a mechanism to express a particular behaviour for its instances, which are Python classes. A metaclass is a blueprint for the class, just as a class is a blueprint for its instances. All metaclasses must derive from type, which is the default metaclass.

Also See, Intersection in Python, Swapcase in Python

Metaclasses in python

In python, a metaclass is used to define how a class behaves. Every class is an instance of a metaclass, and every object is an instance of a class. A metaclass defines the behaviour of its instance class. It is recommended to have prior experience dealing with Python classes to understand metaclasses fully.

Metaclasses can add or remove a method to a regular class. The ‘type’ class is a special class in python that is a meta-class by default. All other classes inherit from the ‘type’ class.

Recommended Topic, Python for Data Science

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 DatabasesNon- relational databasesMongoDBTop-100-sql-problemsinterview-experienceguided-paths

Live masterclass