Single-Case mode
The singleton pattern (Singleton pattern) is a commonly used software design pattern that is primarily intended to ensure that only one instance of a class exists. a singleton can come in handy when you want the entire system to have only one instance of a class.
For example, the configuration information for a server program is stored in a file, and the client reads the configuration file information through a AppConfig class. If the content of the configuration file needs to be used in many places during the run of the program, that is, many places need to create an instance of the AppConfig object, which leads to the existence of multiple AppConfig instance objects in the system, which can seriously waste memory resources. Especially if the configuration file has a lot of content. In fact, a class like AppConfig, we want only one instance object to exist during the run of the program.
The main points of the singleton pattern are three; one is that a class can have only one instance, and the other is that it must create this instance on its own, and thirdly, it must provide this instance to the whole system on its own.
In Python, we can implement a singleton pattern in a variety of ways:
- Using modules
- Use
__new__
- Using adorners (decorator)
- Using meta-classes (Metaclass)
Using modules
In fact, thePython module is a natural singleton pattern .
Because the module generates a file the first time it is imported, the .pyc
file is loaded directly when the second import, .pyc
and the module code is not executed again. Therefore, we just need to define the relevant functions and data in a module, we can get a singleton object.
If we really want a singleton class, consider doing this:
#tests1. Pyclass MyClass (object): def foo (self): print (' Myclass.foo ') My_class_obj=myclass ()
Save the above code in a file tests1.py
, and then use:
From. Tests1 Import My_class_objmy_class_obj.foo ()
Use
__new__
In order for a class to appear only one instance, we can use it __new__
to control the creation of the instance, with the following code:
Class MyClass (object): _instance = None def __new__ (CLS, *args, **kwargs): if not cls._instance: cls. _instance = Super (MyClass, CLS). __new__ (CLS, *args, **kwargs) return cls._instanceclass Herclass (MyClass): A = 1
In the above code, we associate an instance of the class with a class variable _instance
, and if cls._instance
None is created, the instance is returned directly cls._instance
.
Implementation is as follows:
one = Herclass () herclass () print (one = =) #Trueprint (one is) #Trueprint (ID (one), ID (a)) #42818864 4 2818864
Using adorners
We know that adorners (decorator) can dynamically modify the functionality of a class or function. Here, we can also use adorners to decorate a class so that it can generate only one instance, the code is as follows:
From Functools import Wrapsdef Singleton (CLS): instances = {} @wraps (CLS) def getinstance (*args, **kwargs) : If CLS not in instances: instances[cls] = CLS (*args, **kwargs) return INSTANCES[CLS] return Getinstance@singletonclass MyClass (object): a = 1
In the above, we define an adorner singleton
, which returns an intrinsic function getinstance
that determines whether a class is in the dictionary instances
, and if it does not, it will be cls
stored as key as cls(*args, **kw)
value, instances
otherwise, directly back to
Using Metaclass
A meta-class (Metaclass) can control the creation of a class, and it mainly does three things:
- Block creation of classes
- Modifying the definition of a class
- Returns the Modified class
The code to implement a singleton pattern using a meta class is as follows:
Class Singleton (type): _instances = {} def __call__ (CLS, *args, **kwargs): If CLS not in cls._instances:< C11/>CLS._INSTANCES[CLS] = Super (Singleton, CLS). __call__ (*args, **kwargs) return cls._instances[cls]# python2# Class MyClass (object): # __metaclass__ = singleton# python3class MyClass (Metaclass=singleton): Pass
Advantages:
first, instance controlSingleton mode prevents other objects from instantiating copies of their own singleton objects, ensuring that all objects have access to unique instances.
Second, flexibilityBecause classes control the instantiation process, classes can flexibly change the instantiation process.
Disadvantages:
first, the costAlthough the number is small, there will still be some overhead if you want to check for instances of the class every time the object requests a reference. This problem can be resolved by using static initialization.
Ii. Possible confusion of developmentWhen using singleton objects, especially those defined in a class library, developers must remember that they cannot use
NewKeyword to instantiate the object. Because library source code may not be accessible, application developers may unexpectedly find themselves unable to instantiate this class directly.
Iii. Object LifetimeThe problem of deleting a single object cannot be resolved. In a language that provides memory management, such as a. NET framework-based language, only a singleton class can cause an instance to be deallocated because it contains a private reference to the instance. In some languages, such as C + +, other classes can delete object instances, but this results in a floating reference in a singleton class. Supplemental: meta-Class (Metaclass)
Class is also an object
As long as you use the keyword Class,python The interpreter will create an object when it executes.
The following code snippet:
Class MyClass (object): Pass
An object is created in memory and the name is MyClass. this object (class) itself has the ability to create an object (class instance), and that is why it is a class. However, its nature is still an object, so you can do the following with it:
1) You can assign it to a variable
2) You can copy it
3) You can add properties to it
4) You can pass it as a function parameter
Class MyClass (object): passprint (MyClass) # You can print a class because it is actually an object # <class ' __main__. MyClass ' >def Echo (o): print (O) echo (MyClass) # You can pass the class as a parameter to the function # <class ' __main__. MyClass ' >myclass.new_attribute = ' foo ' # You can add properties to the class print (Hasattr (MyClass, ' New_attribute ')) #Trueprint ( Myclass.new_attribute) #fooMyClassMirror =myclass # You can assign a class to a variable print (Myclassmirror ()) # <__main__. MyClass Object at 0x00000000028cde10>
dynamically creating Classes
Because classes are also objects, you can create them dynamically at run time, just like any other object. First, you can create a class in a function, using the class keyword.
def choose_class (name): if name = = ' Foo ': Class foo (object): pass return foo # Returns a class, not an instance of a class else: Class Bar (object): pass return barmyclass = Choose_class (' foo ') print (MyClass) # The function returns the classes, Not an instance of class # <class ' __main__.choose_class.<locals>. Foo ' >print (MyClass ()) # You can create class instances through this class, which is the object # <__main__.choose_class.<locals>. Foo Object at 0x00000000021e5cf8>
But this is not dynamic enough.
Because classes are also objects, they must be generated by something.
Do you remember the built-in function type? This ancient but powerful function lets you know what the type of an object is, just like this:
Print (Type (1)) #<class ' int ' >print (type (' 1 ')) #<class ' str ' >print (Type (MyClass)) # <class ' type ' >print (Type (MyClass ())) #<class ' __main__. MyClass ' >
The type can also dynamically create classes.
Type can work like this:
Type (the class name, the tuple of the parent class (which can be empty for inheritance), the dictionary that contains the property (name and value))
For example, the following code:
Class Myshinyclass (object): Pass
You can create it manually like this:
Myshinyclass=type (' Myshinyclass ', (), {}) # Returns a Class object print (Myshinyclass) # <class ' __main__. Myshinyclass ' >print (Myshinyclass ()) # Creates an instance of the class # <__main__. Myshinyclass Object at 0x0000000002737d68>
The type accepts a dictionary to define properties for the class, so:
Class Foo (object):
Can be translated as:
Foo = Type (' foo ', (), {' Bar ': True})
And you can use Foo as a normal class:
Class Foo (object): bar=trueprint (foo) #<class ' __main__. Foo ' >print (foo.bar) #Truef =foo () print (f) #<__main__. Foo object at 0x0000000001f7de10>print (f.bar) #True
Of course, you can inherit from this class, so the following code:
Class Foochild (Foo): Pass
Can be written as:
Class Foo (object): bar=truefoochild = Type (' Foochild ', (Foo,), {}) print (foochild) # <class ' __main__. Foochild ' >print (foochild.bar) # Bar Property is inherited by Foo # True
Eventually you will want to add a method to your class. You just need to define a function with the proper signature and assign it as a property.
Class Foo (object): bar=truedef Echo_bar (self): print (self.bar) Foochild = Type (' Foochild ', (Foo,), {' Echo_bar ': Echo_bar}) Print (Hasattr (Foo, ' Echo_bar ')) #Falseprint (hasattr (foochild, ' Echo_bar ')) #Truemy_foo = Foochild () My_foo.echo_bar () #True
As you can see, in Python, classes are also objects, and you can create classes dynamically. This is what Python does behind the scenes when you use the keyword class, and this is done through the Meta class.
What the hell is a meta-class?
A meta-class is a "thing" used to create a class. A meta-class is a class of classes.
The function type is actually a meta-class. The type is the meta-class that Python uses to create all the classes behind.
Type is the class that creates the class object. You can see this by checking the __class__ property.
All the things in Python, note that I mean all things--are objects. This includes integers, strings, functions, and classes. They are all objects, and they are all created from a class.
Age = 35print (age.__class__) #<class ' int ' >name = ' bob ' Print (name.__class__) #<class ' str ' >def Foo (): passprint (foo.__class__) #<class ' function ' >class Bar (object): PASSB = Bar () print (b.__ class__) #<class ' __main__. Bar ' >
Now, what is the __class__ attribute for any one __class__?
Print (age.__class__.__class__) #<class ' type ' >print (name.__class__.__class__) #<class ' type ' > Print (foo.__class__.__class__) #<class ' type ' >print (b.__class__.__class__) #<class ' type ' >
Therefore, a meta-class is something that creates objects of this class.
Type is the inner Jianyuan class of Python, and of course, you can also create your own meta-class.
__metaclass__ Properties
You can add the __metaclass__ property to a class when you write it.
Class Foo (object): __metaclass__ = something ...
If you do this, Python will use the Meta class to create the class Foo. Be careful, there's some tricks in there. You first write class Foo (object), but the Class object Foo is not yet created in memory. Python will look for the __metaclass__ attribute in the class definition, and if found, Python will use it to create the class Foo, and if not found, it will use the built-in type to create the class.
When you write the following code:
Class Foo (Bar): Pass
Python does the following:
Is there a __metaclass__ attribute in Foo? If so, Python will create a class object named Foo in memory via __metaclass__ (I'm talking about class objects, please follow my line of thought). If Python does not find __metaclass__, it will continue to look for the __metaclass__ attribute in bar (parent class) and try to do the same thing as before. If Python cannot find __metaclass__ in any parent class, it will look for __metaclass__ in the module hierarchy and try to do the same. If you still can't find __metaclass__,python, you'll use the built-in type to create this class object.
Now the question is, what code can you put in the __metaclass__?
The answer is: You can create something of a class. So what can be used to create a class? Type, or anything that uses the type or subclass type.
Content: custom meta-classes , Why use the Metaclass class instead of a function?, Why should the meta-class be used?
Reference post: http://blog.jobbole.com/21351/
A singleton pattern in Python