Write a single case in--python

Source: Internet
Author: User
Tags class definition python decorator

Original address
Original Address 2
Several implementations of the singleton pattern in Python and its optimization
Reading directory (content)

Single-Case mode
Several ways to implement a singleton pattern
1. Using the module
2. Using adorners
3. Using the class
4. Based on the __new__ method (recommended and convenient for use)
5. Implementation based on Metaclass mode
Related knowledge
Implementing a singleton pattern
Top (go to top)
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.

In Python, we can implement a singleton pattern in a variety of ways

Top (go to top)
Several ways to implement a singleton pattern
1. Using the module
In fact, the Python module is a natural singleton mode, because when the module is first imported, the. pyc file is generated, and when the second import, the. pyc file is loaded directly, 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:

mysingleton.py

Class Singleton (object):
def foo (self):
Pass
Singleton = Singleton ()
Save the above code in the file mysingleton.py, in order to use, directly in other files to import the object in this file, this object is a singleton mode of the object

From a import singleton

2. Using adorners
Copy Code
def Singleton (CLS):
_instance = {}

def _singleton(*args, **kargs):    if cls not in _instance:        _instance[cls] = cls(*args, **kargs)    return _instance[cls]return _singleton

@Singleton
Class A (object):
A = 1

def __init__(self, x=0):    self.x = x

A1 = A (2)
A2 = A (3)
Copy Code

3. Using the class
Copy Code
Class Singleton (object):

def __init__(self):    pass@classmethoddef instance(cls, *args, **kwargs):    if not hasattr(Singleton, "_instance"):        Singleton._instance = Singleton(*args, **kwargs)    return Singleton._instance

Copy Code
In general, you think this completes the singleton pattern, but there is a problem when using multi-threading

Copy Code
Class Singleton (object):

def __init__(self):    pass@classmethoddef instance(cls, *args, **kwargs):    if not hasattr(Singleton, "_instance"):        Singleton._instance = Singleton(*args, **kwargs)    return Singleton._instance

Import threading

def task (ARG):
obj = Singleton.instance ()
Print (obj)

For I in range (10):
t = Threading. Thread (Target=task,args=[i,])
T.start ()
Copy Code
After the program executes, the printing results are as follows:

Copy Code
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
<main. Singleton Object at 0x02c933d0>
Copy Code
It does not seem to be a problem, that is because the execution speed is too fast, if there are some IO operations in the Init method, you will find the problem, below we through the Time.sleep simulation

We add the following code to the __init__ method above:

def __init__(self):    import time    time.sleep(1)

After the program is re-executed, the results are as follows

Copy Code
<main. Singleton Object at 0x034a3410>
<main. Singleton Object at 0x034bb990>
<main. Singleton Object at 0x034bb910>
<main. Singleton Object at 0x034aded0>
<main. Singleton Object at 0x034e6bd0>
<main. Singleton Object at 0x034e6c10>
<main. Singleton Object at 0x034e6b90>
<main. Singleton Object at 0x034bba30>
<main. Singleton Object at 0x034f6b90>
<main. Singleton Object at 0x034e6a90>
Copy Code
There's a problem! A single instance created in the way above cannot support multithreading

WORKAROUND: Lock Up! Non-locking part concurrent execution, lock part serial execution, speed down, but ensure the data security

Copy Code
Import time
Import threading
Class Singleton (object):
_instance_lock = Threading. Lock ()

def __init__(self):    time.sleep(1)@classmethoddef instance(cls, *args, **kwargs):    with Singleton._instance_lock:        if not hasattr(Singleton, "_instance"):            Singleton._instance = Singleton(*args, **kwargs)    return Singleton._instance

def task (ARG):
obj = Singleton.instance ()
Print (obj)
For I in range (10):
t = Threading. Thread (Target=task,args=[i,])
T.start ()
Time.sleep (20)
obj = Singleton.instance ()
Print (obj)
Copy Code

The printing results are as follows:

Copy code
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
< main . Singleton object at 0x02d6b110>
Copy code
That's pretty much the case, but a little bit of a problem is that when the program executes, Time.sleep (20) is executed, and when the object is instantiated, it is already a singleton mode, But we still add the lock, this is not very good, and then some optimization, the Intance method, change to the following line:

Copy Code
@classmethod
def instance (CLS, *args, **kwargs):
If not hasattr (Singleton, "_instance"):
With Singleton._instance_lock:
If not hasattr (Singleton, "_instance"):
Singleton._instance = Singleton (*args, **kwargs)
Return singleton._instance
Copy Code
In this way, a single pattern that can support multithreading is completed.

Full code

The singleton pattern implemented in this way will have limitations when used, and later instantiation must pass obj = Singleton.instance ()

If you use Obj=singleton (), this way is not a singleton

4. Based on the __new__ method (recommended and convenient for use)
From the above example, we can know that when we implement the Singleton, in order to ensure that the thread security needs to join the lock inside

We know that when we instantiate an object, we instantiate the object by executing the __new__ method of the class first (we do not write the default call object.__new__), and then we execute the __init__ method of the class, initialize the object, all we can do based on this, Implementing a singleton pattern

Copy Code
Import threading
Class Singleton (object):
_instance_lock = Threading. Lock ()

def __init__(self):    passdef __new__(cls, *args, **kwargs):    if not hasattr(Singleton, "_instance"):        with Singleton._instance_lock:            if not hasattr(Singleton, "_instance"):                Singleton._instance = object.__new__(cls)      return Singleton._instance

Obj1 = Singleton ()
Obj2 = Singleton ()
Print (OBJ1,OBJ2)

def task (ARG):
obj = Singleton ()
Print (obj)

For I in range (10):
t = Threading. Thread (Target=task,args=[i,])
T.start ()
Copy Code
The printing results are as follows:

Copy Code
<main. Singleton object at 0x038b33d0> <main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
<main. Singleton Object at 0x038b33d0>
Copy Code

In this way, a singleton pattern, when instantiating an object later, is the same as the method of instantiating an object in the usual way, obj = Singleton ()

5. Implementation based on Metaclass mode
Related knowledge
"""
1. Class is created by type, when the class is created, the __init__ method of type executes automatically, class () executes the __call__ method of type (__new__ method of Class, __init__ method of Class)
2. The object is created by the class, when the object is created, the class's __init__ method executes automatically, and the object () executes the call method of the class
"""
Example:

Copy Code
Class Foo:
def Init(self):
Pass

def __call__(self, *args, **kwargs):    pass

obj = Foo ()

Execution of type Pagermethod, call the __new__ method of the Foo class (the object of type), which is used to create the object, and then call the __init__ method of the Foo class (the object of type), which is used to initialize the object.

obj () # call method to execute foo
Copy Code

Use of meta-classes

Copy Code
Class Singletontype (Type):
def Init(Self,*args,**kwargs):
Super (Singletontype,self) __init__ (*args,**kwargs)

def __call__(cls, *args, **kwargs): # 这里的cls,即Foo类    print('cls',cls)    obj = cls.__new__(cls,*args, **kwargs)    cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj)    return obj

Class Foo (metaclass=singletontype): # Specifies that the type of Foo is created as Singletontype
def Init(self,name):
Self.name = Name
def New(CLS, *args, **kwargs):
Return object.__new__ (CLS)

obj = Foo (' xx ')
Copy Code

Implementing a singleton pattern
Copy Code
Import threading

Class Singletontype (Type):
_instance_lock = Threading. Lock ()
def Call (CLS, *args, **kwargs):
If not hasattr (CLS, "_instance"):
With Singletontype._instance_lock:
If not hasattr (CLS, "_instance"):
Cls._instance = Super (SINGLETONTYPE,CLS). Pager (*args, **kwargs)
Return cls._instance

Class Foo (Metaclass=singletontype):
def Init(self,name):
Self.name = Name

Obj1 = Foo (' name ')
Obj2 = Foo (' name ')
Print (OBJ1,OBJ2)
Copy Code

A singleton pattern in Python
I. Overview of the SINGLETON model:

Singleton mode is a kind of common software design pattern. In its core structure, it contains only a special class called a 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 be accessed by the outside world, thus it is convenient to control the number of instances and save system resources. Singleton mode is the best solution if you want to have only one object for a class in the system.

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.

From the specific implementation point of view, is the following three points: first, the Singleton mode class only provides a private constructor, the second is that the class definition contains a static private object of the class, and third, the class provides a static common function to create or get its own static private object.

Second, the application:

Some resource managers are often designed as singleton patterns

In a computer system, resources that need to be managed include software external resources, such as a number of printers per computer, but only one printer Spooler to prevent both printer jobs from being output to the printer at the same time. Each computer can have several fax cards, but there should only be one software that manages the fax card to prevent a communication port from being called simultaneously by two requests.

Resources that need to be managed include internal software resources, for example, most of the software has one (or more) attribute (properties) files to store the system configuration. Such a system should be managed by an object to manage a property file.

The internal resources of the software that need to be managed also include the parts responsible for recording the visitor number of the website, recording the internal events of the software system, the parts of the error message, or the parts that inspect the performance of the system. First, these resource manager artifacts must have only one instance, and the other, they must initialize themselves, and thirdly, allow the entire system to access itself. Therefore, they all satisfy the condition of the singleton mode, and it is the application of the single case pattern.

Three, the advantages and disadvantages of the singleton model:

Advantages:

1. Instance Control

Singleton mode prevents other objects from instantiating copies of their own singleton objects, ensuring that all objects have access to unique instances.

2. Flexibility

Because classes control the instantiation process, classes can flexibly change the instantiation process.

Disadvantages:

1. Overhead

Although 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.

2. Possible development Confusion

When using singleton objects, especially those defined in a class library, developers must remember that they cannot instantiate objects using the New keyword. Because library source code may not be accessible, application developers may unexpectedly find themselves unable to instantiate this class directly.

3. Object Generation Period

The 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 a floating reference to occur in a singleton class.

Iv. in Python, there are several implementations of the singleton pattern.

Method One, implement the __new__ method, and then bind an instance of the class to the class variable _instance, if Cls._instance is None, then the class has not been instantiated, new an instance of the class, and returns, if Cls._ Instance not for none, return directly to _instance, the code is as follows:

Copy Code
Class Singleton (object):
def New(CLS, *args, **kwargs):
If not hasattr (CLS, ' _instance '):
Orig=super (SINGLETON,CLS)
Cls._instance=orig.new(Cls,*args,**kwargs)
Return cls._instance

Class MyClass (Singleton):
A=1

One=myclass ()
Two=myclass ()

One and both are identical and can be checked with ID (), ==,is

Print (ONE.A) # 1
Print (ID (one)) # 2565285375728
Print (ID ()) # 2565285375728
Print (one = =) # True
Print (one is) # True
Copy Code
Method Two, is essentially an upgraded version of method one, using Metaclass (meta-Class) Python advanced usage, the specific code is as follows

Copy Code
"""
__init__ in class Singleton is executed at the time of MyClass Declaration Myclass=singleton ()
When Myclass () executes, the __call__ method of the parent class is executed first (Object,singleton is the parent class of the Myclass.
Based on the depth-first algorithm, the __call__ () in Singleton is executed, and the __call__ () in Singleton writes a singleton mode)
"""
Class Singleton (Type):

def __init__(self, name, bases, dict):    super(Singleton,self).__init__(name,bases, dict)    self._instance = Nonedef __call__(self, *args, **kwargs):    if self._instance is None:        self._instance = super(Singleton,self).__call__(*args, **kwargs)    return self._instance

Class MyClass (Object,metaclass=singleton):
A = 1

One=myclass ()
Two=myclass ()
Print (ID (one)) # 1553247294800
Print (ID ()) # 1553247294800
Print (one = =) # True
Print (one is) # True
Copy Code

Method Three, using the Python decorator (decorator) to implement a singleton mode, which is a more pythonic method; The code of the Singleton class itself is not a singleton, and the code is made by the adorner as follows:

Copy Code
Def Singleton (CLS, *args, **kwargs):
instances = {}

def _singleton():    if cls not in instances:        instances[cls] = cls(*args, **kwargs)    return instances[cls]return _singleton

@singleton
Class MyClass3 (object):
A = 1

one = MYCLASS3 ()
both = MYCLASS3 ()

Print (ID (one)) # 2880466769232
Print (ID ()) # 2880466769232
Print (one = =) # True
Print (one is) # True
Copy Code
Python's singleton pattern, __new__ (), is called before __init__ () to produce an instance object. Using this method and the properties of the class can realize the design pattern of the singleton mode. Singleton mode refers to the creation of a unique object, and a class designed by a singleton pattern can only instantiate an object.

Copy Code
Class Singleton (object):
__instance=none

def __init__(self):    passdef __new__(cls, *args, **kwargs):    if Singleton.__instance is None:        Singleton.__instance=object.__new__(cls,*args, **kwargs)    return Singleton.__instance

One=singleton ()
Two=singleton ()
Print (ID (one)) # 2488569943376
Print (ID ()) # 2488569943376
Print (one = =) # True
Print (one is) # True
Copy Code
Singleton mode is a kind of common software design pattern. In its core structure, it contains only a special class called a single-column class. The single-column mode ensures that there is only one instance of a class in the system and that the instance is easy to access from outside, which facilitates the control of the number of instances and saves system resources. If you want to have only one object for a class in the system, Singleton mode is the last solution.

V. Summary

Content: guarantees that a class has only one instance and provides a global access point to access it.
Scenario: When a class can have only one instance and the customer can access it from a well-known access point
Advantages:
Controlled access to a unique instance
A singleton is equivalent to a global variable, but prevents the namespace from being contaminated
Concepts similar to the singleton mode function: Global variables, static variables (methods)

Write a single case in--python

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.