{"id":1652,"date":"2019-12-27T14:04:18","date_gmt":"2019-12-27T14:04:18","guid":{"rendered":"https:\/\/www.askpython.com\/?p=1652"},"modified":"2019-12-27T14:04:21","modified_gmt":"2019-12-27T14:04:21","slug":"metaclass-in-python","status":"publish","type":"post","link":"https:\/\/www.askpython.com\/python\/metaclass-in-python","title":{"rendered":"Metaclass in Python"},"content":{"rendered":"\n<p>A <strong><em>Metaclass<\/em><\/strong> is the class of a class. Whenever an instance of a class (object) is created, the way that the object behaves is defined by the Class. A Metaclass defines the behavior of the Class itself.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Use of Metaclass in Python<\/h2>\n\n\n\n<p>The reason behind the use of Metaclasses is that Python Classes are Objects themselves. Since Classes are Objects, we can do various operations on it, such as assigning it to a variable, copying, etc.<\/p>\n\n\n\n<p>And since they are objects, we can create them dynamically, as we can do for any other object.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-background has-vivid-green-cyan-background-color has-vivid-green-cyan-color\"\/>\n\n\n\n<p>To understand the concept of Metaclasses better, we first look at how Python defines Classes. The language defines everything as an object, whether it be an <code>int<\/code>, a <code>string<\/code>, or anything else.<\/p>\n\n\n\n<p>To look at the type of any Python object, if you remember, we use the <code>type<\/code> function.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; print(type(123))\n&lt;class &#039;int&#039;&gt;\n&gt;&gt;&gt; print(type(&#x5B;1, 2, 3]))\n&lt;class &#039;list&#039;&gt;\n\n&gt;&gt;&gt; class A():\n...     def __init__(self):\n...             pass\n...\n&gt;&gt;&gt; a = A()\n&gt;&gt;&gt; print(type(a))\n&lt;class &#039;__main__.A&#039;&gt;\n<\/pre><\/div>\n\n\n<p>It returns a <code>class<\/code> for each case, as we can observe. But to see how Python defines the class itself, we simply look at its type.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; print(type(type(123))\n&lt;class &#039;type&#039;&gt;\n&gt;&gt;&gt; print(type(A))\n&lt;class &#039;type&#039;&gt;\n<\/pre><\/div>\n\n\n<p>As you can see, the type(<code>class<\/code>) is the class <code>type<\/code>! So it turns out that the class is defined by a class itself? What is this phenomenon?<\/p>\n\n\n\n<p>This is the concept of a metaclass, which serves to define other classes. Basically, it is a class factory, from which other classes such as <code>int<\/code>s and <code>str<\/code>s can be defined. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"581\" height=\"81\" src=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2019\/12\/metaclass.png\" alt=\"Metaclass\" class=\"wp-image-1653\" srcset=\"https:\/\/www.askpython.com\/wp-content\/uploads\/2019\/12\/metaclass.png 581w, https:\/\/www.askpython.com\/wp-content\/uploads\/2019\/12\/metaclass-300x42.png 300w\" sizes=\"auto, (max-width: 581px) 100vw, 581px\" \/><figcaption>Metaclass hierarchy<\/figcaption><\/figure>\n\n\n\n<p><code>type<\/code> is the metaclass which the language uses to create <em>an<\/em> object. (which is why every object has a type)<\/p>\n\n\n\n<p>And because <code>type<\/code> is a metaclass, we can create other classes from it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-background has-vivid-green-cyan-background-color has-vivid-green-cyan-color\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Creating Classes Dynamically<\/h2>\n\n\n\n<p>We can create classes dynamically by instantiation from the type constructor: <code>type(name, bases, attr)<\/code><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong><em>name<\/em><\/strong> -&gt; name of the Class<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li><strong><em>bases<\/em><\/strong> -&gt; classes from which the new class inherits from<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li> <strong><em>attr<\/em><\/strong> -&gt; dictionary of attributes + methods contained within the class<\/li><\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&gt;&gt;&gt; Animal = type(&#039;Animal&#039;, (), dict(__init__ = lambda self: None, worth = lambda self, value: value))\n<\/pre><\/div>\n\n\n<p>This is the same as:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nclass Animal():\n    def __init__(self):\n        pass\n    \n    def worth(self, value):\n        return value\n<\/pre><\/div>\n\n\n<p>The first bit of code is much easier to write as compared to the second. Writing the class body even during dynamic declaration doesn&#8217;t provide much flexibility. <\/p>\n\n\n\n<p>Therefore, Metaclasses provide a powerful and easy way of dynamically creating new classes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-background has-vivid-green-cyan-background-color has-vivid-green-cyan-color\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Creating custom Metaclasses<\/h2>\n\n\n\n<p>To create our own metaclass, we need to inherit the existing `type` metaclass and override some special methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>__<strong>new<\/strong>__() -> This is called before <code>__init__()<\/code>. It is responsible for creating the object and returns it.<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li> __<strong>init<\/strong>__() -> This is for initializing the newly created object, which is passed as a parameter (the <code>self<\/code> parameter)<\/li><\/ul>\n\n\n\n<p>The following snippet shows how a metaclass can be created:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nclass MyMetaclass(type):\n    def __new__(cls, name, bases, dict):\n        print(&#039;Creating a new object of&#039;, name)\n        # Invoke __new__() method of the metaclass type\n        return super(MyMetaclass, cls).__new__(cls, name, bases, dict)\n\n    def __init__(cls, name, bases, dict):\n        print(&#039;Initialising class&#039;, name)\n        super(MyMetaclass, cls).__init__(name, bases, dict)\n<\/pre><\/div>\n\n\n<p>Now that we have created our custom Metaclass, we need to make sure we create other classes that use our metaclass.<\/p>\n\n\n\n<p>To do this, we pass the <code>metaclass<\/code> parameter in the new class definition, which tells the class to use our custom metaclass as it&#8217;s own metaclass, instead of <code>type<\/code>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nclass Student(metaclass=MyMetaclass):\n    def __init__(self, name):\n        self.name = name\n\n    def get_name(self):\n        return self.name\n<\/pre><\/div>\n\n\n<p>Here, <code>Student<\/code> uses <code>MyMetaclass<\/code> as its metaclass. Therefore, when creating an instance of Student, our custom metaclass methods will be called, instead of the <code>type<\/code> metaclass.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nstud = Student(&#039;Amit&#039;)\nprint(stud.get_name())\nprint(&#039;Type of Student object:&#039;, type(stud))\nprint(&#039;Type of Student Class:&#039;, type(Student))\n<\/pre><\/div>\n\n\n<p>Output<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nCreating a new object of Student\nInitialising class Student\nAmit\nType of Student object: &lt;class &#039;__main__.Student&#039;&gt;\nType of Student Class: &lt;class &#039;__main__.MyMetaclass&#039;&gt;\n<\/pre><\/div>\n\n\n<p><strong>NOTE<\/strong>: Old Python versions of 2.7 or below use the <code>__metaclass__<\/code> keyword for specifying the metaclass used. Python3 changed this behavior to pass the <code>metaclass<\/code> as a parameter.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-background has-vivid-green-cyan-background-color has-vivid-green-cyan-color\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusions<\/h2>\n\n\n\n<p>While metaclasses serve as a very powerful way for creating custom APIs and define their behavior during object and Class creation, they are very rarely ever used in practice, as there are other workaround methods for the same. <\/p>\n\n\n\n<p>This article only serves as a starting point for the topic, and about understanding how Python defines everything in terms of the <code>type<\/code> metaclass. <\/p>\n\n\n\n<p>We looked at how metaclasses can be created, and the methods which are called during the creation of Classes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-background has-vivid-green-cyan-background-color has-vivid-green-cyan-color\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<p>StackOverflow post on Metaclasses (This provides an in-depth discussion on this topic. Recommended if you want to learn more about metaclasses): <a href=\"https:\/\/stackoverflow.com\/questions\/100003\/what-are-metaclasses-in-python\" class=\"rank-math-link\" target=\"_blank\" rel=\"noopener\">https:\/\/stackoverflow.com\/questions\/100003\/what-are-metaclasses-in-python<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Metaclass is the class of a class. Whenever an instance of a class (object) is created, the way that the object behaves is defined by the Class. A Metaclass defines the behavior of the Class itself. Use of Metaclass in Python The reason behind the use of Metaclasses is that Python Classes are Objects [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1652","post","type-post","status-publish","format-standard","hentry","category-python"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/1652","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/comments?post=1652"}],"version-history":[{"count":0,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/1652\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media?parent=1652"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/categories?post=1652"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/tags?post=1652"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}