+

What are python metaclasses for?

Metaclass &this is the class of the class. Whenever a class (object) is instantiated, the behavior of the object is determined by the class. The metaclass defines the behavior of the class itself.

Using the Metaclass in Python

The reason for using metaclasses is because Python classes are themselves objects. Since classes are objects, we can perform various operations with them, such as assigning them to a variable, copying, etc.

And since they are objects, we can create them dynamically like any other object.

< ! - ptnonline336 ->


To better understand the concept of metaclasses, we`ll first see how Python op thinns classes. The language defines everything as an object, be it int , string or whatever.

If you remember to look at the type of any Python object, we`re using the type function.

 & gt; & gt; & gt; print (type (123)) & lt; class `int` & g t; & gt; & gt; & gt; print (type ([1, 2, 3])) & lt; class `list` & gt; & gt; & gt; & gt; class A (): ... def __init __ (self): ... pass ... & gt; & gt; & gt; a = A () & gt; & gt; & gt; print (type (a)) & lt; class `__main __. A` & gt; 

As we can see, it returns the class for each case. But to see how Python defines the class itself, we`ll just look at its type.

 & gt; & gt; & gt; print (type (type (123)) & lt; class `type` & gt; & gt; & gt; & gt; print (type (A)) & lt; class` type` & gt; 

As you can see, type ( class ) &this is the type of the class! It turns out that the class is defined by the class itself? What is this phenomenon?

This is the concept of a metaclass that serves to define other classes, basically a class factory from which other classes such as int s and str s can be defined.

< img loading = "lazy" class = "alignnone" src = "https://pythononline.ru/wp-content/uploads/2020/09/img-103.png" alt = "Metaclass python" width = "581" height = "81" />

type &this is the metaclass that the language uses to create an object. (So every object has a type)

And since type &is a metaclass, we can create other classes from it.

Dynamically create classes

We can create classes dynamically by instantiating from the constructor type (name, bases, attr) : type (name, bases, attr)



  • name - & gt; class name
  • base - & gt; classes from which the new class inherits
  • attr - & gt; dictionary of attributes + methods contained in the class
 & gt; & gt; & gt; Animal = type (`Animal`, (), dict (__ init__ = lambda self: None, worth = lambda self, value: value)) 

This is the same as:

 class Animal (): def __init __ (self): pass def worth (self, value): return value 

The first code snippet is much easier to write than the second. Writing a class body even during dynamic declaration does not provide much flexibility.

Therefore, metaclasses provide a powerful and easy way to dynamically create new classes.

Create your own metaclasses

To create our own metaclass, we need to inherit the existing `type` metaclass and override some special methods:

  • __new __ () - & gt; This is called before __init __ () . It is responsible for creating an object and returning it.
  • __init __ () - & gt; This is to initialize the newly created object, which is passed as a parameter ( self parameter)

The following snippet shows how a metaclass can be created:

 class MyMetaclass (type): def __new __ (cls, name, bases, dict): print (`Creating a new object of`, name) # Invoke __new __ () method of th e metaclass type return super (MyMetaclass, cls) .__ new __ (cls, name, bases, dict) def __init __ (cls, name, bases, dict): print (`Initialising class`, name) super (MyMetaclass, cls) .__ init __ (name, bases, dict) 

Now that we have created our own metaclass, we need to make sure that we create other classes that use our metaclass.

To do this, we we pass the metaclass parameter to the new class definition, which tells the class to use our own metaclass as its own metaclass, rather than type .

 class Student (metaclass = MyMetaclass): def __init __ (self, name): self.name = name def get_name (self): return self.name 

Here Student < / code> uses MyMetaclass as its metaclass. Therefore, when instantiating Student, our own metaclass methods will be called instead of the type metaclass.

 stud = Student (`Amit `) print (stud.get_name ()) print (` Type of Student object: `, type (stud)) print (` Type of Student Class: `, type (Student)) 

Output

 Creating a new object of Student Initialising class Student Amit Type of Student object: & lt; class `__main __. Student` & gt; Type of Student Class: & lt; class `__main __. MyMetaclass` & gt; 

Older versions of Python 2.7 or earlier use the __metaclass__ keyword to specify the metaclass to use. Python3 changed this behavior to pass metaclass as a parameter.

Conclusions

While metaclasses serve as a very powerful way to create custom APIs and define their behavior in creation time of objects and classes, they are very rarely ever used in practice, since there are other workarounds for them. You can read more on this topic at stackoverflow.com .



Get Solution for free from DataCamp guru