Python 单例模式(3种方式)
Posted yangzhizong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 单例模式(3种方式)相关的知识,希望对你有一定的参考价值。
方式一:
# 单例模式: # 实现目的:实例化多次,得到的实例是同一个,就是同一个对象,同一个名称空间(更加节省空间) ####################################方式一:在类内部定义一个类方法################################# import settings class Mysql: __instance=None #定义一个变量,来接收实例化对象,方便下面做判断 def __init__(self,ip,port): self.ip=ip self.port=port # @classmethod #做成类方法 #绑定给Mysql类去直接调用实例化 def from_conf(cls): #目的是要调取mysql这个类通过从配置文件读取IP、端口参数,完成调用init方法,拿到一个实例化init方法的对象 # mysql(settings.IP,settings.PORT) #如果是这样每次,实例化出的对象,都是不同的名称空间,但是数据是同一份 # return cls(settings.IP,settings.PORT) #cls(ip,port) 就是调用init方法 #演变最终版:思考可以统一定义一个初始变量__instance=None,将第一次实例的对象传给他,有每次外面再访问就直接 if cls.__instance is None: cls.__instance=cls(settings.IP,settings.PORT) return cls.__instance #之前版本: # p1=Mysql.from_conf() # print(p1) #<__main__.Mysql object at 0x02BE82B0> #数据是同一份,但每次实例化,指向的都是不同的内存地址 # p2=Mysql.from_conf() # print(p2) #<__main__.Mysql object at 0x02C1AB90> #这样写就完美的实现了隔离: #升级版本后,可以实现,访问存的东西一样的,可以指向同一个内存空间 obj=Mysql.from_conf() print(obj.__dict__) #也可以传入新的参数,另外新造一个名称空间 obj2=Mysql(‘3.3.3.3‘,8888) print(obj2.__dict__)
方式二:
#方式二:装饰器 import settings def singleton(cls): __instance=cls(settings.IP,settings.PORT) #给Mysql的init方法传参,实例化得到一个对象,__instance def wrapper(*args,**kwargs): #判断外面调用时,是否有传值进来 if len(args) == 0 and len(kwargs)== 0: return __instance #用户没有传传参,意思直接返回默认settings的值 return cls(*args,**kwargs) #否则会创建新的值 return wrapper @singleton class Mysql: ##Mysql=singleton(Mysql) #Mysql=wrapper def __init__(self,ip,port): self.ip=ip self.port=port def aa(self): print(‘IP地址:%s 端口:%s‘%(self.ip,self.port)) #实现的结果是:想要实现的是mysql不传参数,默认指向同一个实例 #没有传参数的调用:保证每次实例化得到的是同一个内存地址 obj1=Mysql() #wrapper() obj2=Mysql() #wrapper() print(obj1.__dict__,id(obj)) #{‘ip‘: ‘1.1.1.1‘, ‘port‘: 3306} 45554896 print(obj2.__dict__,id(obj)) #{‘ip‘: ‘1.1.1.1‘, ‘port‘: 3306} 45554896 #有传参的情况下,创建新的 obj2=Mysql(‘2.2.2.2‘,666) print(obj2.__dict__)
方式三:
方式三:自定义元类 #自定义元类控制类的调用过程,即类的实例化:__call__ import settings class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): super(Mymeta,self).__init__(class_name,class_bases,class_dic) # obj=self.__new__(self) #造出一个mysql的对象meta # # self.__init__(obj,settings.IP,settings.PORT) #w从配置文件中加载配置完成mysql对象的初始化 # # self.__instance=obj #拿到一个默认对象,保存到一个类属性中 self.__instance=self.__new__(self) #先造一个空对象 __instance self.__init__(self.__instance,settings.IP,settings.PORT) #为空的对象初始化独有的属性 print(self.__instance.__dict__) def __call__(self, *args, **kwargs): #在调用用阶段及会触发 if len(args)==0 and len(kwargs)==0: return self.__instance ##如果没有会直接传入 obj=self.__new__(self) self.__init__(obj,*args,**kwargs) return obj class Mysql(object,metaclass=Mymeta): def __init__(self,ip,port): self.ip=ip self.port=port #拿到的是同一个内存空间地址 obj=Mysql() obj1=Mysql() obj2=Mysql() print(obj) print(obj1) print(obj2) #拿到是单独的内存地址 obj2=Mysql(‘3.3.3.3‘,8888) print(obj2.__dict__)
以上是关于Python 单例模式(3种方式)的主要内容,如果未能解决你的问题,请参考以下文章