以下摘自https://zhuanlan.zhihu.com/p/269012332
instances = {}
def singleton(cls):
def get_instance(*args, **kw):
cls_name = cls.__name__
if not cls_name in instances:
instance = cls(*args, **kw)
instances[cls_name] = instance
return instances[cls_name]
return get_instance
@singleton
class User:
_instance = None
def __init__(self, name):
self.name = name
u1 = User('zhouxixi1')
u1.age = 20
u2 = User('zhouxixi2')
print(u2.age)
assert u1 is u2
执行顺序
instances = {} # 定义空字典
u1 = User('zhouxixi1') # 实例化User类,传入name=zhouxixi1
# 本来应该走class User这一步的,因为加了装饰器,所以先运行装饰器,随后在装饰器内运行类
def singleton(cls): # cls为接受的类,此处为传入的User类
def get_instance(*args, **kwargs) # 此处接受类的参数,此处为传入的zhouxixi1(放在args中)
cls_name = cls.__name__ # 把cls.__name__赋值给cls_name ,此处cls.__name__为User类的名字,即User
if cls_name not in instances: # 如果cls_name 没有在instances 字典中,则继续
instance = cls(*args, **kwargs) # 此处要执行类了,实例化类User,此处args中包含了zhouxixi1
def __init__(self, name) # 执行构造函数,此处name为传入的*args,即zhouxixi1
self.name = name # zhouxixi1赋值给self.name
instance = cls(*args, **kwargs) # 回到这里,生成类的实例instance
instances[cls_name] = instance # 在字典instances中加入key:cls_name即User,value:instance ,即User object
return instances[cls_name] # 返回User object
# u1 = User('zhouxixi1')执行完成,获得u1:<__main__.User object at 0x000001EB1E42CD90>
u1.age = 20
u2 = User('zhouxixi2') # 同u1的执行步骤
...
...
...
# 以上中间步骤省略
if cls_name not in instances: # 执行到这里,因为instances已经包含User了,所以就不往下走了
return instances[cls_name] # 直接返回和u1同一个User object
print(u2.age) # u1,u2是同一个object,所以都有age属性
assert u1 is u2 # true
关于一直没用到的 return get_instance,
需要知道的是装饰器必须返回一个可被调用对象callable,固定格式吧,需要把get_instance返回回去
return get_instance