Python meta classes
Published: 2020-04-21 20:59:52

<!-- wp:heading -->
<h2>What is a python metaclass</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Metaclasses in python are a useful way to describe the behavior of a class. <strong>Metaprogramming</strong>&nbsp;is a programming technique used in a computer software component to have the ability to treat other components as described in their data. It means that a program can be designed to understand and even change other programs or modify it's specification while executing.  Python has a perfect syntax structure and modules that support meta class definition. Many people are better off not using metaclasses in python, but if you're using the Django web framework, metaclasses are used in model and form definition. Read more on <a href="https://clouditate.com/what-is-a-meta-class-in-django/">Django metaclasses</a>. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>A meta class in python can simply be defined as a class of <strong>class</strong> that describes the behavior of the <strong>class</strong>. A class is the instance of a meta class</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><a rel="noreferrer noopener" href="https://en.wikipedia.org/wiki/Lisp_(programming_language)" target="_blank">Lisp programming language</a> has a reputation for having a good meta programming facility and easy syntax. I advice you check basic Lisp meta programming.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Python has old style and new style class definition syntax. Let's explore of those class varieties:</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Old style python class definition</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Classes are not defined by inheriting from a base class. An instance of an old-style class is implemented from an instance.  In old classes, obj.__class__ represent the class and type(obj) return the instance of the class. Here is an example:</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code {"language":"python"} -->
<pre class="wp-block-syntaxhighlighter-code">#
#
# Old style class definition

class Hello:
   pass

obj = Hello()
obj.__class__

type(obj)

#
#
#</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>The old style python class definition was removed in python 3 &gt;. Let's look at the new style of defining classes.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>New style python class definition</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>A class is created by inheriting from&nbsp;Object class. It is the only way to define a class since <strong>python 3</strong>. In the new style definition obj.__class__ is the same as type(obj). That's the main difference between the two python class definition. Example code:</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code {"language":"python"} -->
<pre class="wp-block-syntaxhighlighter-code">#
#
# New class definition example

class MyClass(Object):
   pass

obj = MyClass()
print(type(obj) is obj.__class__)

# end example
#
#</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>The above code will return true because obj.__class__ is same as type(obj). </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Python classes and types</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Everything in python<strong> is an object. So are classes. Let's look at the type of class. The type of an object is a class, but the type of</strong> class is <strong>type</strong>. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Type</strong> is the metaclass and classes are the instances of the metaclass. This means that any python 3 class is an instance of the meta class.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Creating custom python metaclass</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Python allows a programmer to customize the class creation by passing the metaclass&nbsp;keyword in the class definition syntax.  You can also do so by inheriting a class in which a metaclass was defined. Here is an example.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code {"language":"python"} -->
<pre class="wp-block-syntaxhighlighter-code">#
#
# Define Meta Class
class MyMetaClass(type):
    pass

# Define a class that takes the MyMetaClass 
class MyClass(metaclass=MyMetaClass):
    pass

# A class thatinherits a MyClass class
class MyChildclass(MyClass):
    pass

#
#
#
</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p>If you define a class and decide not to define a custom meta class, the default <strong>type</strong> is used.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>__new__ and __init__ , python meta classes</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>You can define python metaclasses using<strong> __new__ and __init__</strong> keywords. Let's look at the example implimentation.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code {"language":"python"} -->
<pre class="wp-block-syntaxhighlighter-code">#
#
#

class MetaClass(type):
    def __new__(cls, name, bases, dict):
        pass

class AnotherMetaClass(type):
    def __init__(self, name, bases, dict):
        pass

#
#
#</pre>
<!-- /wp:syntaxhighlighter/code -->

<!-- wp:paragraph -->
<p><strong>__new__</strong> is used if you want to define a dictionary (dict) or tuples before you create the class. <strong>__new__ </strong>is called after the object has been created to initialize it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Singleton Class using a Metaclass</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Singleton class is a class that can be instantiated by only one object. In python you can implement a singleton design using metaclasses. Example code.</p>
<!-- /wp:paragraph -->

<!-- wp:syntaxhighlighter/code {"language":"python"} -->
<pre class="wp-block-syntaxhighlighter-code">#
#
#
class SingletonMetaClass(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta,cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class MyClass(metaclass=SingletonMeta):
    pass
#
#
#</pre>
<!-- /wp:syntaxhighlighter/code -->