1、使用类的__new__方法
# 使用__new__方法,python自省
class Singleton(object):
def __new__(cls, *args, **kwargs):
# 如果没有隐变量_instance就调用__new__一个,python自省
if not hasattr(cls, "_instance"):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kwargs)
return cls._instance
利用hasattr反射技术,判断是否有_instance属性,没有则调用object的__new__方法创建一个对象赋值给私有变量
使用方法
让需要单例模式的类继承该类即可
# 继承该单例模式
class MyClass(Singleton):
pass
2、采用装饰器
利用闭包定义一个装饰器
# 装饰器版本
def singletonDecor(cls):
# 存储对象实例的字典
instance = {}
def getInstance(*args, **kwargs):
if cls not in instance.keys():
instance[cls] = cls(*args, **kwargs)
return getInstance
判断定义的类是否是在存在对象实例的字典中,不存在则创建一个对象
使用方法
@singletonDecor
class MyTest3():
pass
在需要单例的类上添加装饰器即可
3、采用装饰器,线程安全
# 线程安全的单例模式
from functools import wraps
from threading import RLock
def singleton(cls):
"""线程安全的单例装饰器"""
instances = {}
locker = RLock()
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
with locker:
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
引入RLock,在创建对象的时候加锁,@wraps(cls)的作用是保证被装饰器修饰的函数的结构不变,比如可以保证装饰器修饰的函数的__name__
的值保持不变等