通俗来讲:一个类只有一个实例
举例:一个文件的操作只能通过唯一的一个实例进行,否则多进程多线程下无法操作
应用场景:服务器配置信息一份即可,不需要频繁创建
实现方式:
- 使用模块。模块是天然的单例模式,第一次导入时会生成.pyc文件,第二次导入时直接加载此文件
- 使用装饰器
装饰器
def singleton(cls):
_instance = {} # 定义一个字典用来保存类的实例对象
def _singleton(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return _singleton
@singleton
class A(object):
a = 1 # 类变量
def __init__(self, x=0):
self.x = x # 实例变量
print('这是A的类初始化方法')
a1 = A(2)
a2 = A(3)
print(id(a1), id(a2))
print(a1.a, a1.x, a2.a, a2.x)
- 使用类
- 基于__new__方法(推荐使用)。实例化时先执行__new__返回一个实例化对象,再调用__init__对这个对象进行初始化。因此在__new__里先判断是不是存在实例,存在就返回,不存在就创建。
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self, *args, **kwargs):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
with Singleton._instance_lock: # 在获取对象属性的的时候就加锁,避免其他人在获取对象并创建对象的过程中
if not hasattr(cls, '_instance'):
Singleton._instance = super().__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()