创建python单例实例的装饰器

环境: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

小结:

相比较而言,我更喜欢第二种方法.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值