In this article, we're going to discuss metaclasses , why and when we should use them, and what the alternatives are. This is a fairly advanced Python topic and the following prerequisite is expected —
Note: This article is about Python 3.3 and up
In Python, everyone has some type associated with it. For example, if we have a variable that has an integer value, then its type — int. You can get the type of anything using the type () function.
Type of num is: & lt; class 'int' & gt; Type of lst is: & lt; class 'list' & gt; Type of name is: & lt; class 'str' & gt;
Every type in Python is defined by a class . So in the above example, unlike C or Java, where int, char, float are the main data types, in Python they are objects of class int or str. Thus, we can create a new type by creating a class of that type. For example, we can create a new type Student by creating a class Student .
pass p >
# Print type of student class object
" Type of stu_obj is: "
Type of stu_obj is: & lt; class '__main __. Student' & gt;
A class is also an object , and like any other object, it is an instance of something called a metaclass . The special type class creates these class objects. The class of type is the default metaclass , which is responsible for creating classes. For example, in the above example, if we try to figure out the type of the class Student , it turns out to be a type .
Type of Student class is: & lt; class 'type' & gt;
Since classes are also objects, they can be modified in the same way. We can add or subtract fields or methods in the class just like we did with other objects. For example —
This whole meta thing can be summarized as — Metaclass create Classes and Classes creates objects
The metaclass is responsible for generating classes, so we can write our own metaclasses to change the way we generate classes by performing additional actions or injecting code. We usually don't need custom metaclasses, but sometimes we do.
There are problems for which metaclass and nonmetaclass solutions are available (often simpler), but in some cases only a metaclass can solve this problem. We will discuss such a problem in this article.
Creating our own metaclass
To create our own metaclass, our custom the metaclass must inherit the type metaclass and usually override —
We can create classes using the type () function directly. It can be called in the following ways —
Consider this example —
Traceback (most recent call last): File "& lt; stdin & gt;", line 2, in & lt; module & gt; File "& lt; stdin & gt;", line 8, in __new__ TypeError: Inherited multiple base classes !!!
Solving the metaclass problem
There are some problems that can be solved by both decorators (easily) and metaclasses. But there are several problems that can only be achieved with metaclasses. For example, consider a very simple code repetition problem.
We want to debug class methods, we need to ensure that whenever a class method is executed, it will print the fully qualified name before executing its body.
The very first solution that comes to our mind is — this is using decoration methods , below is some code example:
Output: p >
Full name of this method: Calc.add 5 Full name of this method: Calc.mul 10
This solution works great, but there is one problem: what if we want to apply this method decorator to all subclasses that inherit this class Calc . In this case, we must separately apply the decorator method to each subclass, as we did with the Calc class.
The problem is that if we have there are many such subclasses, then in this case we will not like adding a decorator to each separately. If we know in advance that every subclass should have this debug property, then we should look for a metaclass solution.
Take a look at this metaclass solution , the idea is that the classes will be generated normally and then immediately wrapped with the debug method decorator —
Full name of this method: Calc_adv.mul 6
When to use metaclasses strong>
Most of the time we do not use metaclasses, they are like black magic and usually for something complex, but there are few cases where we use metaclasses:
According to Tim Peters
Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
This article courtesy of Atul Kumar . If you are as Python.Engineering and would like to contribute, you can also write an article using contribute.python.engineering or by posting an article contribute @ python.engineering. See my article appearing on the Python.Engineering homepage and help other geeks.
Please post comments if you find anything wrong or if you'd like to share more information on the topic discussed above.