方式一:
- # 单例模式:
- # 实现目的: 实例化多次, 得到的实例是同一个, 就是同一个对象, 同一个名称空间 (更加节省空间)
- #################################### 方式一: 在类内部定义一个类方法 #################################
- 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__)
来源: http://www.bubuko.com/infodetail-2687019.html