Python单例模式

一、先认识几个魔术方法,对理解实例创建有帮助

  • __init__、__new__、__call__

    一、__new__方法
    1、__new__方法负责创建一个实例对象,在对象被创建的时候调用该方法它是一个类方法。
    2、__new__方法在返回一个实例之后,会自动的调用__init__方法,对实例进行初始化
    3、如果__new__方法不返回值,或者返回的不是实例,那么它就不会自动的去调用__init__方法
    
    二、__init__ 方法
    1、__init__ 方法负责将__new__方法创建的实例对象进行初始化,
    2、执行顺序在__new__方法创建出一个实例后对实例属性进行初始化
    3、__init__方法可以没有返回值。
    
    三、__call__方法
    1、使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用。
    2、实例()调用的时候自动执行__call__方法,其实是把一个类的实例化对象变成了可调用对象
    

二、 模块实现单例

class Test01:
    def __init__(self):
        #类实例化多少次就会执行多少遍
        print("__init__")
cl1 = Test01()
cl2 = Test01()
print(cl1)
print(cl2)
print(cl1 is cl2)
使用:在其他类使用的时候直接导入cl1即可实现单例
输出:
__init__
__init__
<__main__.Test01 object at 0x10efd64e0>
<__main__.Test01 object at 0x10f01c1d0>
False

三、装饰器实现单例

def test01(cls):
    def get_class(*args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = cls(*args, **kwargs)
        return cls._instance
    return get_class
@test01
class Test01:
    def __init__(self):
        print("只执行一次")
cl1 = Test01()
cl2 = Test01()
print(cl1)
print(cl2)
输出:
<__main__.Test01 object at 0x1016d11d0>
<__main__.Test01 object at 0x1016d11d0>

四、使用__new__方法实现单例

class Test01(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,"_instance"):
            #_instance: 类实例的key名称
            cls._instance = super().__new__(cls, *args, **kwargs)
        print(cls.__dict__)
        return cls._instance

cl1 = Test01()
cl2 = Test01()
print(cl1 is cl2)
输出:
{'__module__': '__main__', '__new__': <staticmethod object at 0x107af1588>, '__dict__': <attribute '__dict__' of 'Test01' objects>, '__weakref__': <attribute '__weakref__' of 'Test01' objects>, '__doc__': None, '_instance': <__main__.Test01 object at 0x107af14e0>}
True

五、使用元类metaclass实现单例

"使用场景:当多个类需要使用单例模式,可以用元类,只需要给类增加一个__metaclass__ = Test01属性即可"
一、__init__+__call__实现
class Test01(type):
    def __init__(self,*args, **kwargs):
        #init只会被调用一次,所以父类初始化方法只会被调用一次
        print("__init__")
        self.__instance = None
        super().__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        #call方法,类被实例化几次就会被调用几次
        print("__call__")
        if self.__instance is None:
            self.__instance = super().__call__(*args, **kwargs)
        return self.__instance

class demo01(metaclass=Test01):
    __metaclass__ = Test01

cl1 = demo01()
cl2 = demo01()
print(cl1)
print(cl2)
输出:
__init__
__call__
__call__
<__main__.demo01 object at 0x103aae278>
<__main__.demo01 object at 0x103aae278>

二、__new__+__call__实现
class Test01(type):
    def __new__(cls, name,bases,attrs):
        #new方法只执行一次
        print ("__new__")
        attrs["_instance"] = None
        return  super().__new__(cls,name,bases,attrs)

    def __call__(self, *args, **kwargs):
        #类实例多少次call方法执行多少次
        print ("__call__")
        if self._instance is None:
            self._instance = super().__call__(*args, **kwargs)
        return self._instance

class Demo01(metaclass=Test01):
    __metaclass__ = Test01

cl1 = Demo01()
cl2 = Demo01()
print(cl1)
print(cl2)
输出:
__new__
__call__
__call__
<__main__.Demo01 object at 0x100c973c8>
<__main__.Demo01 object at 0x100c973c8>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值