What are Metaclasses in Python?

Aro Militosyan
6 min readOct 14, 2022

--

What is a metaclass and why do you need to know about metaclasses? Metaclasses are esoteric OOP concepts hidden in almost all Python code. We use them whether we know it or not. Few languages ​​in the programming world support this concept. There are languages ​​in which there is no concept of a metaclass. However, Python provides the idea of ​​a metaclass.

In fact, it is often said that everything in Python is an object.

Thus, to fully understand Python, you need to understand its basic structures (such as objects and classes) so that you can understand what is actually going on inside the code. An object, of course, is an instance of a class, and when you hear that everything in Python is an object, the curious (that is, us) have the question (right?): What if classes are also objects? So what creates the class?

I know that this is difficult to understand at once, but, nevertheless, we should try to understand. If classes are objects that create objects, then how do we call the objects that create classes? Trust me, this is not the chicken or egg puzzle of which came first. There is a clear answer here, such objects are called metaclasses. The simplest type of metaclass is when the metaclass (type) takes only one parameter as an input parameter and returns the type of the object passed as a parameter. In this case, it doesn’t work as a metaclass. When a type receives three input parameters, it acts as a metaclass and creates a class based on the parameters passed. The class name must be passed as parameters,“parents” (classes from which inheritance occurs) and dictionary attributes. The last two parameters can be empty.

Let’s take an example:

It will return us this result:

<class ‘type’>

0:

Note that the second parameter must be a tuple.

Classes and objects:

The first thing we need to discuss is the relationship between objects and classes.

You have the following class.

We are creating an empty class that does not contain any attributes or methods. We then represent it in a population object and at the end we ask which class it is the created instance, using the type function.

It will return us:

<class ‘__main__.Person’>

The class representing the collection object is Person and it has been defined in the same module. Okay, but what is a class type? Let’s try.

It’ll return us

<class ‘type’>

<class ‘type’>

<class ‘type’>

Let’s remember that everything in Python is an object. Classes are also objects. As a result, the class must have a type.

What is a class type?

For example:

The result will be:

<class ‘__main__.Foo’>:

<class ‘type’>

The type of the x is the class Foo, but the type of the Foo itself is a type.

Another example to make it clearer.

As a result of the program execution, it will return:

<class ‘type’>

<class ‘type’>

<class ‘type’>

<class ‘type’>

<class ‘type’>

A type is a metaclass whose classes are instances.

Let’s take a look at the example above:

1. x is an instance of the class Foo.

2. Foo is an instance of the metaclass type.

3. type is also an instance of the metaclass, so it is itself an instance.

This diagram will help you understand better:

It is interesting that the type of a class is a type, isn’t it?

This is because it is known to us as a metaclass. A metaclass creates instances of classes in the same way that classes create instances of objects.

The question arises, how can we use it?

Let’s understand in which case we will use it. Since a metaclass creates a class in certain steps, it can be useful if we can access and manipulate that process and thereby create our own metaclass, which will create a class in a different way (not as a type ). This is a bit like a decorator. Decorators in Python allow us to manipulate functions before they are called. In fact, as we’ll see, they have a lot in common.

A metaclass is the blueprint for the class itself, just as a class is a blueprint for instances of that class.

The default metaclass is a type, and all metaclasses must derive from type.

Class instances:

The first thing to understand when talking about metaclasses is how a class is created in Python with a default metaclass type. When a class is created, Python takes some variables, such as the class name and the base classes that the class inherits from and basically creates a dictionary by calling the dunder method named __prepare__ . The body of the class is invoked to populate the dictionary with attributes and methods.

The last step is to give the name of the created class as well as the base classes and the above mentioned dictionary as parameters.

It looks like this:

Person = type(‘Person’, (Base1, Base2), cls_dict)

The Person object is now a class that inherits from its parents, Base1 and Base2, and has the attributes and methods defined by cls_dict.

If we were to recreate an empty class named Person, we could do it dynamically like this:

Person = type(‘Person’, (), {})

I think it’s important to know the inner workings of Python in order to understand what’s going on underneath the code and to know when to use the right tools for the job. If we have many classes that share a common base class, the metaclass will definitely be inherited.

Singleton class implementation in Python using metaclasses:

The result of the project will be the following:

TRUE:

MYSQL 3306

ORACLE 3306

Factory Class:

The metaclass is mainly used as a factory class. When we create an object by calling a class, Python creates a new class by calling the metaclass. Let’s use the type, create dynamic classes.

Let’s take an example:

As a result of this project, we will receive:

red

But in this example, we won’t be able to reuse the init and getColor functions, so we use the class-factory approach. Let’s take an example to make it clearer:

will bring us back

red:

__new__ and __init__

Metaclasses can also be defined in either of the two ways shown below.

__new__ is used when we want to define a dictionary or create tuples before creating a class. The return value of __new__ is usually an instance of cls. And __init__ is usually called after the object has been created to initialize it.

The metaclass also has a __call__ method. We can also override other methods of a class by defining a special __call__() method in the metaclass that allows special behavior when the class is called.

I hope this article was helpful to you.

Thank you.

#metaclass #in_python #python #what_are_metaclass_in_python #Metaclasses

--

--