This article brings you an introduction to two implementation methods of python singletons (with code). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
In the past two days, I have been looking at the code I wrote before, so I just sorted out the things I have used. The singleton mode is often used in daily code work,
So here is a summary of the singleton methods that have been implemented in different ways before
Decorator method
This method is also commonly used in work. It is also more convenient to use. The code is implemented as follows
def Singleton(cls): _instance = {} def _singleton(*args, **kwargs): if cls not in _instance: _instance[cls] = cls(*args, **kwargs) return _instance[cls] return _singleton
If a class we are working on needs to use a singleton, it can be implemented in a way similar to the following:
@Singleton class A(object): def __init__(self, x): self.x = x
Personally I still like this way
Classic way to achieve
There are actually some issues that need to be paid attention to here. Let’s take a look at the possible error codes first.
class Member(object): @classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance
At first glance, this class seems to have implemented a singleton, but There is a potential problem here, that is, if it is a multi-threaded situation, writing like this will cause problems, especially when there are some time-consuming operations in the initialization object of the current class.
For example, the following code:
#! /usr/bin/env python3 # .-*- coding:utf-8 .-*- import time import threading import random class Member(object): def __init__(self): time.sleep(random.randint(1,3)) @classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance def task(arg): obj = Member.instance() print(obj) for i in range(5): t = threading.Thread(target=task, args=[i,]) t.start()
The execution result of this code will be that multiple objects are instantiated, causing the singleton you wrote to have no effect
Of course Naturally, we will think of locking and controlling it through locks, so we change the above code:
#! /usr/bin/env python3 # .-*- coding:utf-8 .-*- import time import threading import random class Member(object): _instance_lock = threading.Lock() def __init__(self): i = random.randint(1, 3) print(i) time.sleep(i) @classmethod def instance(cls, *args, **kwargs): with Member._instance_lock: if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance def task(): obj = Member.instance() print(obj) for i in range(5): threading.Thread(target=task,).start()
But there is another problem with the above code, that is, when After we have instantiated it, we will request the lock every time we call instance, so this is not good, so we change this part of the code again:
@classmethod def instance(cls, *args, **kwargs): if not hasattr(Member, "_instance"): with Member._instance_lock: if not hasattr(Member, "_instance"): Member._instance = Member(*args, **kwargs) return Member._instance
This is a good implementation A single instance that can be used in multiple threads
The above is the entire content of this article. For more exciting content about python, you can pay attention to the Python video tutorial and python on the php Chinese website Article tutorial column! ! !
The above is the detailed content of Introduction to two implementation methods of python singleton (with code). For more information, please follow other related articles on the PHP Chinese website!