转载自:https://blog.csdn.net/lqxqust/article/details/51910007
Singleton模式即单例对象必须必须保证只有一个实例存在。可以说Singleton是设计模式中最基本一种设计模式,在学习设计模式时一般都会先了解该模式。在Python中实现单例模式有很多方法,下面简单总结以下,可以根据情况选择适合自己业务场景的一种进行实现。
1. 如果在C++中实现过单例模式,在Python中比较常想到的实现方法是借助__new__
方法实现:
class Singleton(object): instance = None def __new__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super().__new__(cls, *args, **kwargs) return cls.instance t1 = Singleton() t2 = Singleton() assert id(t1) == id(t2)
该方法基本可以保证只有一个实例,但存在并发的问题。
2. 在C++中实现Singleton模式的时候也会考虑多线程的问题,在Pyhton中同样存在该问题,可以通过加锁进行解决。
import threading class Singleton(object): vars = {} single_lock = threading.Lock() def __new__(cls, *args, **kwargs): if cls in cls.vars: return cls.vars[cls] cls.single_lock.acquire() try: if cls in cls.vars: return cls.vars[cls] cls.vars[cls] = super().__new__(cls, *args, **kwargs) return cls.vars[cls] finally: cls.single_lock.release()
以上两种都是在类似C++的语言中实现的常用方法,但是在Python中实现不那么Pytonic,并且被子类重载可能还存在问题。
3. 在《改善Python程序的91个建议》中介绍了一种方法,Python的import机制天然支持单例的实现。
1. 所有变量都会绑定到模块
2. 模式只初始化一次
3. import机制是线程安全的
该放很多情况下都可以满足单例的使用,实现有时觉得有点隐晦。
4. 有没有更Pythnic得方法,并且有比较易于使用的呢?大Python当时是无所不能了O(∩_∩)O~,通过使用元类来实现。元类就是用来控制创建类的类。
class SingletonMeta(type): def __init__(cls, name, bases, namespaces): super().__init__(cls, name, bases, namespaces) cls.instance = None def __call__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super().__call__(*args, **kwargs) else: print("instance already existed!") return cls.instance class Singleton(meta=Singleton): pass t1 = Singleton() t2 = Singleton()
实现了__call__
方法这个类就成为可调用的,类似于重载了括号操作符,因为在元类中实现__call__
,则使用Singleton()
实例化类时就会调用__call__
,对其进行了单例创建的控制。
4. 还有一种Pythonic的方法时使用decorator实现
def singleton(cls, *args, **kwargs): instances = {} def wrapper(): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return _wrapper @singleton class Singleton(object): pass t1 = Singleton() t2 = Singleton()
以上是Python中常见的实现单例模式的方法,在实际开发中,可以根据应用场景选择自己喜欢的方式实现,个人觉得通过元类或装饰器方式实现还是非常的方便和Pythonic。