A custom metaclass controls the instantiation behavior of a class

Three elements of an object: id, type, value

When doing some optimizations, you may encounter this situation, multiple objects have the same value (value), but there are multiple ids, for the same value we want to use,

The program requests multiple memory spaces from the system

a = [1, 2, 3, 523241, 31, 5215, 63, 634]
b = [1, 2, 3, 523241, 31, 5215, 63, 634]
print(a == b)
print(a is b)

The result is as follows

True
False

This is not what we want, we want these objects to use the same memory space

Then, using the singleton pattern can optimize this problem very well

Quoting the concept of the singleton pattern:

The singleton pattern is a commonly used software design pattern. In its core structure there is only one special class called singleton class. The singleton mode can ensure that there is only one instance of a class in the system and the instance is easy to access from the outside world, thereby facilitating the control of the number of instances and saving system resources. If you want to have only one object of a certain class in the system, the singleton pattern is the best solution. Obviously there are three main points of the singleton pattern: one is that a class can only have one instance; the other is that it must create this instance by itself; the third is that it must provide this instance to the entire system by itself.

okay, again for this list, I'll write it again:

a = [1, 2, 3, 523241, 31, 5215, 63, 634]
b = [1, 2, 3, 523241, 31, 5215, 63, 634]

Now the question is the question: how to optimize it into a singleton pattern, even if id(a) == id(b) / a is b

We know that both a and b are objects instantiated by the list class

a = [1, 2, 3, 523241, 31, 5215, 63, 634]

a = list([1, 2, 3, 523241, 31, 5215, 63, 634])

We also know that the metaclass can control the creation behavior of the class through the __Init__ method

Similarly, the metaclass can also control the instantiation behavior of the class through the __call__ method. In this case, the metaclass can control the creation of a list object

Since the default a is b -->False, we have reason to believe that there is such a logic in the creation process of the list's metaclass control list object: when the list is instantiated, each instantiation will apply for a memory space for the variable,

Then it's easy to figure out this logic and implement the singleton pattern: when we want to instantiate the list, don't directly apply for memory space, but first determine whether there is an object to be created (a) with the same value (b) ), if any, then

Don't apply for memory space, I will directly assign b to a, then ensure that a points to the address of b.

>>> a = [1, 2, 3, 523241, 31, 5215, 63, 634]
>>> b =a
>>> b
[1, 2, 3, 523241, 31, 5215, 63, 634]
>>> a
[1, 2, 3, 523241, 31, 5215, 63, 634]
>>> id(a)
48912392
>>> id(b)
48912392
>>>

The problem turns into:
how to use the __call__ method, so that the class will judge whether the object exists when it instantiates the object, and if it does not exist, create a new object.

class Mylist(type):

    def  __init__ (self, class_name, class_bases, class_dic): #Here
         self .__instance stores the object instantiated by Mylis, which is convenient to check whether the object already exists 
        . __instance = []
    
    #Here self refers to the class Mylis (classes are also objects, if you understand this, you will know why self is used instead of cls) 
    def  __call__ (self, *args, ** kwargs): #Three
         steps of class instantiation 
        # 1. Create an empty object 
        obj = list. __new__ (self)
         # 2. Initialize the object 
        self. __init__ (obj, *args, ** kwargs)
         # 3. Return the object 
        if  not obj in self. __instance :
             #If it does not exist An object with the same value as itself, then add this object to the instantiation list and instantiate this new object 
            self. __instance .append(obj)
             return obj
        else :
             #If the object with the same value as its own has been instantiated, then refer to the object with the same value as its own object 
            return self. __instance [self. __instance .index(obj)]

#We need to customize a list, here named Mylis, let it inherit the list class, and then you can use Mylis in the future. 
class Mylis(list,metaclass= Mylist):
     pass

Check it out:

a = Mylis ([1, 2, 3, 523241, 31, 5215, 63, 634 ])
b = Mylis ([1, 2, 3, 523241, 31, 5215, 63, 634 ])
 print (a == b)
 print (a is b)

result:

True
True

Here, we have mastered the method of defining the instantiation behavior of the metaclass control class through the implementation of the singleton pattern.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325011785&siteId=291194637