单例模式
ps:类只要加括号就会生成一个新的对象,无论参数是否相同,单例模式排除在外.
class Demo: pass obj1 = Demo() obj2 = Demo() print(id(obj1)) # 1594519955888 print(id(obj2)) # 1594519955832
单例:
多次调用类拿到的是同一个对象
单例的实现:
<1>基于classmethod
class Mysql(object): _instance = None def __init__(self, host, port): self.host = host self.port = port @classmethod def singelton(cls): if not cls._instance: cls._instance = cls('127.0.0.1',8080) obj1 = Mysql.singelton() obj2 = Mysql.singelton() obj3 = Mysql('168.192.1.1',8088) print(id(obj1), id(obj2), id(obj3)) # 1731962064 1731962064 1736639656680
<2>基于装饰器
# 基于装饰器 本质:会将紧挨着它的变量名当做参数传入 def singelton(cls): _instance = cls('127.0.0.1',8080) def inner(*args, **kwargs): if args or kwargs: obj = cls(*args, **kwargs) # cls 是真正的 Mysql 类 return obj return _instance return inner @singelton # Mysql = singelton(Mysql) 函数加括号优先级最高,此时 Mysql就是inner class Mysql(object): def __init__(self, host, port): self.host = host self.port = port obj1 = Mysql() # 其实是 inner() obj2 = Mysql() obj3 = Mysql('168.192.1.1',8088) print(id(obj1), id(obj2), id(obj3)) # 2661019235384 2661019235384 2661019235328
<3>基于元类
class MyClass(type): def __call__(self, *args, **kwargs): # 调用 Mysql 中的 _instance if not getattr(self,'_instance'): # 此时的self是Mysql self._instance = super().__call__(*args, **kwargs) # 调用父类的__call__产生对象赋值给 _instance 这个对象就是Mysql的对象 # __call__固定会做三件事: # 1.产生空对象 __new__ # 2.初始化对象 __init__ # 3.返回该对象 return obj return self._instance pass class Mysql(object, metaclass=MyClass): # 类加括号会走它元类中的__call__方法 _instance = None def __init__(self, host, port): self.host = host self.port = port obj1 = Mysql('168.192.1.1',8088) obj2 = Mysql('168.192.1.1',9999) print(id(obj1), id(obj2)) # 2107832088112 2107832088112
<4>基于__new__
class Mysql(object): _instance = None def __init__(self, host, port): self.host = host self.port = port # __new__拦截类的创建过程,在类创建前先走__new__, 这里的__new__在Mysql实例化时触发 def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = object.__new__(cls) # 这里的cls每次都是最后实例化时那个Mysql return cls._instance obj1 = Mysql('168.192.1.1',8088) obj2 = Mysql('168.192.1.1',9999) print(id(obj1), id(obj2)) # 1512390747976 1512390747976
<5>基于模块
class Settings(object):pass settings = Settings()
from 单例设计模式1 import settings def func(): print(id(settings))
# 1. from 单例设计模式1 import settings print(id(settings)) # 3078907535488 from 单例设计模式1 import settings print(id(settings)) # 3078907535488 # 模块导入一次后就不会在导入 # 2. from 单例设计模式1 import settings from 单例设计模式2 import func print(id(settings)) # 2381785037456 func() # 2381785037456 # 3. from 单例设计模式1 import settings,Settings print(id(settings)) # 2080793135592 print(id(Settings())) # 2080793135424