使用new方法实现单例模式
每个实例的创建是通过__new__方法,所以如果要实现一个类只能有一个实例就得重写__new__函数。
class A: _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: print("创建了一个实例") obj = super().__new__(cls, *args, **kwargs) cls._instance = obj return obj return cls._instance def __init__(self): print('开始初始化')
执行:
a = A()
输出为:
创建了一个实例
开始初始化
执行:
b = A()
输出为:
开始初始化
执行:
print(id(a), id(b)) # 每个实例的id一样
输出:
140078083206056 140078083206056
使用共享属性实现单例模式
与上一种方法不同的是,此种方法当执行__new__方法后,每次生成一个新的实例。只不过每个实例共享同样的属性,因此实际使用的效果和上面的方法一样。但严格意义上讲,我认为这不算单例。
class A: _myDict = {} def __new__(cls, *args, **kwargs): obj = super().__new__(cls, *args, **kwargs) obj.__dict__ = cls._myDict print("创建了一个实例") return obj def __init__(self): print("开始初始化")
执行:
a = A()
输出为:
创建了一个实例
开始初始化
执行:
b = A()
输出为:
创建了一个实例
开始初始化
执行:
print(id(a), id(b)) # 每个实例的id不一样
输出为:
140078082716952 140078082716504
执行:
a.a = '1' # 此时对实例a添加一个a属性 pirnt(b.a) # 通过b得到了与a一模一样的值
使用装饰器实现单例模式
装饰器的特色就是给函数添加额外的功能,同样可以在类上使用装饰器,来限制实例的个数。但此种方法与上两种不同的是,前两种类的__init__方法在生成实例后都被执行了执行了一次,而此种方法只有在第一次生成实例时才调用__init__方法。
def oneObject(cls): def wrap(*args, **kwargs): if not hasattr(cls, '_instance'): obj = cls(*args, **kwargs) cls._instance = obj return obj return cls._instance return wrap @ oneObject class A: def __init__(self): print("已经创建了一个实例")
执行:
a = A()
输出为:
已经创建了一个实例
执行:
b = A() # 注意,没有执行__init__函数
print(id(a), id(b))
输出为:
140357050460928 140357050460928