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
