Singletons and metaclasses

Let's start with a brief introduction to metaclasses. A metaclass is a class of a class, which means that the class is an instance of its metaclass. With metaclasses, programmers get an opportunity to create classes of their own type from the predefined Python classes. For instance, if you have an object, MyClass, you can create a metaclass, MyKls, that redefines the behavior of MyClass to the way that you need. Let's understand them in detail.

In Python, everything is an object. If we say a=5, then type(a) returns <type 'int'>, which means a is of the int type. However, type(int) returns <type 'type'>, which suggests the presence of a metaclass as int is a class of the type type.

The definition of class is decided by its metaclass, so when we create a class with class A, Python creates it by A = type(name, bases, dict):

  • name: This is the name of the class
  • base: This is the base class
  • dict: This is the attribute variable

Now, if a class has a predefined metaclass (by the name of MetaKls), Python creates the class by A = MetaKls(name, bases, dict).

Let's look at a sample metaclass implementation in Python 3.5:

class MyInt(type):
    def __call__(cls, *args, **kwds):
        print("***** Here's My int *****", args)
        print("Now do whatever you want with these objects...")
        return type.__call__(cls, *args, **kwds)


class int(metaclass=MyInt):
    def __init__(self, x, y):
        self.x = x
        self.y = y


i = int(4,5)

The following is the output of the preceding code:

Singletons and metaclasses

Python's special __call__ method gets called when an object needs to be created for an already existing class. In this code, when we instantiate the int class with int(4,5), the __call__ method of the MyInt metaclass gets called, which means that the metaclass now controls the instantiation of the object. Wow, isn't this great?!

The preceding philosophy is used in the Singleton design pattern as well. As the metaclass has more control over class creation and object instantiation, it can be used to create Singletons. (Note: To control the creation and initialization of a class, metaclasses override the __new__ and __init__ method.)

The Singleton implementation with metclasses can be explained better with the following example code:

class MetaSingleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(MetaSingleton, 
                cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Logger(metaclass=MetaSingleton):
    pass

logger1 = Logger()
logger2 = Logger()
print(logger1, logger2)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.33.157