• 实现单例的四种方法


    1. 储备知识

    # 储备知识
    #4 、自定义元类:
    class Mymeta(type):
        # 来控制类Foo的创建
        def __init__(self,class_name,class_bases,class_dic): #self=Foo
    
            if not class_name.istitle():
                raise TypeError('类名的首字母必须大写傻叉')
    
            if not class_dic.get('__doc__'):
                raise TypeError('类中必须写好文档注释,大傻叉')
    
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    #
        # 控制类Foo的调用过程,即控制实例化Foo的过程
        def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}
    
            #1 造一个空对象obj
            obj=object.__new__(self)
    
            #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
            self.__init__(obj,*args,**kwargs)
    
            return obj

    ·····························

    # 单例:所有实例化出来的对象都是同一个

    # 所有的配置信息放在一个类中,拿配置文件就实例化类的对象就行
    # (问题是每次拿到的对象虽然一样,但内存地址不同,就用到了单例)

    # 第一种 基于__new__的单例
    # 通过使用__new__来控制实例的创建过程
    
    # 实例化对象的的过程:1.先产生一个空对象(__new__),然后在调用init方法
    class Singleton(object):
        __instance = None
        def __new__(cls,*args,**kwargs):
            if not cls.__instance:
                # 实际object.__new__(self)返回的就是一个对象
                cls.__instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
            return cls.__instance
    
    a1 = Singleton()
    a2 = Singleton()
    # 第二种:基于模块的单例模式(用来导入的时候) # 原因:第一次调用模块时,执行一遍,第二次以后调用都不执行(模块调用只执行一次) class Settings(object): x = 100 def foo(self): print("foo") settings = Settings() # 另一个py文件中调用这个模块 # from funcs import settings (这样内存中就有了settings对象,以后用的都是一个了,实现了单例) # 第三种 # 思路: 定义一个类(__instance = None),在类中定义一个类方法 singleton(cls),如果__instance为空,则创建对象 import settings class MySQL(object): __instance = None def __init__(self,ip,port): self.ip = ip self.port = port # 可以保证只有一个对象,但还是可以通过调用类产生新对象(解决:用元类来控制实例化的过程__call__) @classmethod def singleton(cls): if not cls.__instance: # 创建对象 obj = cls(settings.IP,settings.PORT) cls.__instance = obj return cls.__instance obj4=MySQL.singleton() obj5=MySQL.singleton() # id 相同 # 以上参数为配置文件中同一套参数,实现了单例

    # 第四种方式,利用元类来实现单例 # 调用类产生对象,实际是调用原类中的__call__方法,自定义__call__方法 # 定义元类 class MyMeta(type): __instance = None # 控制类Foo的调用过程,即控制实例化Foo的过程 def __call__(self, *args, **kwargs): if not MyMeta.__instance: __instance = object.__new__(self) self.__init__(__instance,*args,**kwargs) MyMeta.__instance = __instance return MyMeta.__instance class Printer(metaclass = MyMeta): print(1111) p1 = Printer() p2 = Printer() # id 地址一样
  • 相关阅读:
    杨辉三角
    100以内的素数
    九九
    MyDate
    计算器
    100以内素数
    杨辉三角形
    九九乘法表
    窗口关闭事件
    计算器界面
  • 原文地址:https://www.cnblogs.com/Afrafre/p/10384792.html
Copyright © 2020-2023  润新知