环境:python 3.5
单例模式网上有很多种方法,多少有一些问题,以下是我推荐的两种方法。
方法一:使用metaclass
class Singleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance
else:
return self.__instance
使用方法:
class myclass(metaclass=Singleton)
pass
以上方法是从网上查到的。
方法二:方法装饰器
def Singleton(cls):
assert inspect.isclass(cls) , 'The Singleton decorator can only be applied to class'
def run_only_once(func):
"""
使__init__仅仅运行一次
"""
@wraps(func)
def _wrapper_init(self,*args, **kwargs):
if not hasattr(self,"___init__called"):
self.___init__called=True
return func(self,*args, **kwargs)
return _wrapper_init
def newfunc(clsobj, *args, **kwargs):
"""
使用元编程确保仅仅实现一个单例
"""
if not hasattr(clsobj, "__instance"):
setattr(clsobj, "__instance", object.__new__(clsobj))
return getattr(clsobj, "__instance")
#拦截__new__方法
setattr(cls,"__new__",classmethod(newfunc))
# 由于在创建cls时,python会调用__new__来创建实例,然后再调用实例的__init__
# 这样通过在__new__使用object__new__能确保每次实例化cls时均返回同一个实例。
# 但是python还是会调用__init__,这样会导致__init__方法每实例一次就会调用一次
# 这种行为不是我们需要的,因此我们通过run_on_once装饰器做一定的处理,使__init__只调用一次
setattr(cls, "__init__", run_only_once(cls.__init__))
return cls
使用方法:
@Singleton
class A(object):
pass
小结:
相比较而言,我更喜欢第二种方法.