A metaclass is a class/object which defines a type/class of other classes. In Python a metaclass can be a class, function or any object that supports calling an interface. This is because to create a class object; its metaclass is called with the class name, base classes and attributes (methods). When no metaclass is defined (which is usually the case), the default metaclass type is used.

For example:

When a class is created, the interpreter:

  1. Gets the name of the class.
  2. Gets the base classes of the class.
  3. Gets the metaclass of the class. If it is defined, it will use this first. Otherwise, it will check in the base classes for the metaclass. It it can't find a metaclass in the base class, the type object is used instead.
  4. Gets the variables/attributes in the class and stores them as a dictionary.
  5. Passes this information to metaclass as metaclass(name_of_class, base_classes, attributes_dictionary) and it returns a class object.

For example:

When type is called, its __call__ method is called. This method in turn calls the __new__ and __init__ methods. The __new__ method creates a new object, whereas the __init__ method initializes it. We can easily play with methods. This is a working example:

When running the code, we get:

When running the code, we get:

Normally we need to override only one method __new__ or __init__. We can also use function instead of a class. Here is an example:

Gives us the following output:

Gives us the following output:

Other then modifying base classes and methods of classes to be created, metaclasses can also modify instance creation process. This is because when we create an instance (ik = Kls()), this is like calling the class Kls. One point to note is that whenever we call an object its type's __call__ method is called. So in this case the class type is metaclass hence its __call__ method will be called. We can check like this:

The output is as follows:

Equipped with this information, if we go to the start of our discussion about the class creation process, it ended with a call to the metaclass object, which provided a class object. It was like this:

Hence this call should call the metaclass's type. The metaclass type is the metaclass's metaclass! We can check this as follows:

Gives us the following output:

To Practice: Try this interactive course on the basics of Lists, Functions, Packages and NumPy in Python.

About The Author

  • thenavaneethan

    Nice Explanation 🙂

    In the last example, The super meta class (SuperMeta) called only once for the first object ik = Kls(‘arun’),

    it was not called for ik2 = Kls(‘avni’)

    Is it related to singleton?

    • When a metaclass is specified, the __call__ method is executed, without instantiating the class itself. Whereas when you instantiate the class, the __init__ method is called.

      • thenavaneethan

        Thanks for the response.

        Let me clear on that.

        In the last example, When you create this object

        ik = Kls(‘arun’)

        we get,

        SuperMeta Called

        class created

        MyMeta called class ‘__main__.Kls’ (‘arun’,) {}


        The metaclass of Kls is called that is MyMeta also the metaclass of MyMeta is called that is SuperMeta

        At the same time,

        ik2 = Kls(‘avni’)

        when you create one more instance for the class Kls

        only the metaclass of Kls is called

        MyMeta called class ‘__main__.Kls’ (‘avni’,) {}

        The SuperMeta class is not being called.

        My doubt is SuperMeta class is metaclass of MyMeta class.

        whenever __call__ method of MyMeta is called, SuperMeta’s __call__ method also has to be called isn’t?

        so, both ik1 and ik2 object creation has been done through metaclass.So, Has it to reach through SuperMeta?

        we are getting SuperMeta’s output for only ik1 object.

        can you explain bit clear.

        • Okay, so I was a bit unclear myself ;-).

          I talked to one of the writers (Xiaonuo),

          When Kls is constructed at line ‘class Kls(metaclass=MyMeta)’, MyMeta is instantiated which triggers SuperMeta’s __call__ method because it’s MyMeta’s metaclass. When Kls is instantiated at line ‘ik = Kls(‘arun’)’ and line ‘ik2 = Kls(‘avni’)’, MyMeta’s __call__ method is called because it’s Kls’s metaclass.

          One thing to realize is that the instantiation of MyMeta happens at line ‘class Kls(metaclass=MyMeta)’ while its __call__ method is called at line ‘ik = Kls(‘arun’)’ and ‘ik2 = Kls(‘avni’)’. MyMeta’s __call__ method is called after its class has been instantiated.

          I hope that clears things up!

  • Pingback: Python:How to implement a subscriptable class in Python (subscriptable class, not subscriptable object)? – IT Sprite()