1.方法1,程序运行过程中,某个类对象只有1个,该类对象的实例对象可以有无数个,根绝这点,让类对象持有一个实例化对象,重写类对象的__new__方法,始终返回持有的这个实例化对象,即可实现单例模式。
class Person1:
_single = None
def __new__(cls, *args, **kwargs):
if not cls._single:
cls._single = object.__new__(cls,*args,**kwargs)
return cls._single
p1 = Person1()
p2 = Person1()
print(id(p1)==id(p2))
输出:True。
注意__new__方法中的cls是类对象本身,查看cls.__class__可以输出type。
2.方法2:装饰器实现。需要了解函数作用域,封闭作用域,以及函数闭包:函数闭包的特性,用人话来讲就是,嵌套定义在非全局作用域里面的函数能够记住它在被定义的时候它所处的封闭命名空间。
def dec(cls):
dct = dict()
def func(*args,**kwargs):
k = '{}{}{}'.format(cls.__name__,args,kwargs)
print('args',args)
print('kwargs',kwargs)
print('cls:',cls.__class__) # cls: <class 'type'> 是类对象
if k not in dct:
# v = object.__new__(cls,*args,**kwargs)
v = cls(*args,**kwargs) # cls是类对象
dct[k] = v
return dct[k]
return func
@dec
class Person2():
pass
p1 = Person2()
p2 = Person2()
print(p1.__class__) # <class '__main__.Person2'>
print(id(p1)==id(p2)) # True
3.方法3:元类实现,需要了解元类的原理,如何修改类。
class Singleton(type):
_single = None
def __call__(self, *args, **kwargs):
if not self._single:
self._single = super(Singleton,self).__call__(*args,**kwargs)
return self._single
class P(metaclass=Singleton):
pass
p1 = P()
p2 = P()
print(id(p1)==id(p2))