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.