{"id":216,"date":"2024-01-25T16:14:14","date_gmt":"2024-01-25T16:14:14","guid":{"rendered":"https:\/\/learnpython.elegantwallp.com\/?p=216"},"modified":"2024-01-25T16:14:14","modified_gmt":"2024-01-25T16:14:14","slug":"python-metaclass","status":"publish","type":"post","link":"https:\/\/learnpython.elegantwallp.com\/2024\/01\/25\/python-metaclass\/","title":{"rendered":"Python Metaclass"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you\u2019ll learn about the Python metaclass and understand how Python uses the metaclasses to create other classes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction to the Python Metaclass<\/h2>\n\n\n\n<p>A metaclass is a&nbsp;<a href=\"https:\/\/www.pythontutorial.net\/python-oop\/python-class\/\">class<\/a>&nbsp;that creates other classes. By default, Python uses the&nbsp;<code><a href=\"https:\/\/www.pythontutorial.net\/python-oop\/python-type-class\/\">type<\/a><\/code>&nbsp;metaclass to create other classes.<\/p>\n\n\n\n<p>For example, the following defines a\u00a0<code>Person<\/code>\u00a0class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Person: def __init__(self, name, age): self.name = name self.age = age<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>When Python executes the code, it uses the&nbsp;<code>type<\/code>&nbsp;metaclass to create the&nbsp;<code>Person<\/code>&nbsp;class. The reason is that the&nbsp;<code>Person<\/code>&nbsp;class uses the&nbsp;<code>type<\/code>&nbsp;metaclass by default.<\/p>\n\n\n\n<p>The explicit\u00a0<code>Person<\/code>\u00a0class definition looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Person(object, metaclass=type): def __init__(self, name, age): self.name = name self.age = age<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The&nbsp;<code>metaclass<\/code>&nbsp;argument allows you to specify which metaclass class to use to define the class. Therefore, you can create a custom metaclass that has its own logic to create other classes. By using a custom metaclass, you can inject functionality into the class creation process.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Python metaclass example<\/h2>\n\n\n\n<p>First, define a custom metaclass called\u00a0<code>Human<\/code>\u00a0that has the\u00a0<code>freedom<\/code>\u00a0attribute sets to\u00a0<code>True<\/code>\u00a0by default:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Human(type): def __new__(mcs, name, bases, class_dict): class_ = super().__new__(mcs, name, bases, class_dict) class_.freedom = True return class_<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Note that the\u00a0<code>__new__<\/code>\u00a0method returns a new class or a class object.<\/p>\n\n\n\n<p>Second, define the\u00a0<code>Person<\/code>\u00a0class that uses the\u00a0<code>Human<\/code>\u00a0metaclass:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Person(object, metaclass=Human): def __init__(self, name, age): self.name = name self.age = age<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The\u00a0<code>Person<\/code>class will have the\u00a0<code>freedom<\/code>\u00a0attribute as shown in the\u00a0class variables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>pprint(Person.__dict__)<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>mappingproxy({'__dict__': &lt;attribute '__dict__' of 'Person' objects>, '__doc__': None, '__init__': &lt;function Person.__init__ at 0x000001E716C71670>, '__module__': '__main__', '__weakref__': &lt;attribute '__weakref__' of 'Person' objects>, 'freedom': True})<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Put it all together.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from pprint import pprint class Human(type): def __new__(mcs, name, bases, class_dict): class_ = super().__new__(mcs, name, bases, class_dict) class_.freedom = True return class_ class Person(object, metaclass=Human): def __init__(self, name, age): self.name = name self.age = age pprint(Person.__dict__)<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Metaclass Parameters<\/h2>\n\n\n\n<p>To pass parameters to a metaclass, you use the keyword arguments. For example, the following redefines the\u00a0<code>Human<\/code>\u00a0metaclass that accepts keyword arguments, where each argument becomes a class variable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Human(type): def __new__(mcs, name, bases, class_dict, **kwargs): class_ = super().__new__(mcs, name, bases, class_dict) if kwargs: for name, value in kwargs.items(): setattr(class_, name, value) return class_<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The following uses the\u00a0<code>Human<\/code>\u00a0metaclass to create a\u00a0<code>Person<\/code>\u00a0class with the\u00a0<code>country<\/code>\u00a0and\u00a0<code>freedom<\/code>\u00a0class variables set to\u00a0<code>USA<\/code>\u00a0and\u00a0<code>True<\/code>\u00a0respectively:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>class Person(object, metaclass=Human, country='USA', freedom=True): def __init__(self, name, age): self.name = name self.age = age<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Here are Person class variables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>pprint(Person.__dict__)<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>mappingproxy({'__dict__': &lt;attribute '__dict__' of 'Person' objects>, '__doc__': None, '__init__': &lt;function Person.__init__ at 0x0000018A334235E0>, '__module__': '__main__', '__weakref__': &lt;attribute '__weakref__' of 'Person' objects>, 'country': 'USA', 'freedom': True})<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Put it all together.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from pprint import pprint class Human(type): def __new__(mcs, name, bases, class_dict, **kwargs): class_ = super().__new__(mcs, name, bases, class_dict) if kwargs: for name, value in kwargs.items(): setattr(class_, name, value) return class_ class Person(object, metaclass=Human, freedom=True, country='USA'): def __init__(self, name, age): self.name = name self.age = age pprint(Person.__dict__)<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">When to use metaclasses<\/h2>\n\n\n\n<p>Here\u2019s the quote from\u00a0Tim Peter\u00a0who wrote the Zen of Python:<\/p>\n\n\n\n<p>Metaclasses are deeper magic that 99% of users should never worry about it. If you wonder whether you need them, you don\u2019t (the people who actually need them to know with certainty that they need them and don\u2019t need an explanation about why).Tim Peter<\/p>\n\n\n\n<p>In practice, you often don\u2019t need to use metaclasses unless you maintain or develop the core of large frameworks such as Django.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: in this tutorial, you\u2019ll learn about the Python metaclass and understand how Python uses the metaclasses to create other classes. Introduction to the Python Metaclass A metaclass is a&nbsp;class&nbsp;that creates other classes. By default, Python uses the&nbsp;type&nbsp;metaclass to create other classes. For example, the following defines a\u00a0Person\u00a0class: When Python executes the code, it uses [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32],"tags":[],"class_list":["post-216","post","type-post","status-publish","format-standard","hentry","category-8-metaprogramming-exceptions"],"_links":{"self":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/216","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/comments?post=216"}],"version-history":[{"count":1,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/216\/revisions"}],"predecessor-version":[{"id":217,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/216\/revisions\/217"}],"wp:attachment":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/media?parent=216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/categories?post=216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/tags?post=216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}