前提介绍: 为了减少系统频繁初始化类,需要自定义单例基类,通过继承方式将当前类变成单例,单例类实现如下。
class Singleton(object):
_instance = None
@classmethod
def instance(cls):
if not cls._instance:
cls._instance = cls()
return cls._instance
问题描述: 在各个单例类之间无继承关系时,上面的实现是没有问题的,但是如果出现单例类之间有继承关系的,就会出现问题。子类不能正确初始化自己类的实例,测试代码如下:
class Parent(Singleton):
pass
class Child(Parent):
pass
if __name__ == '__main__':
parent = Parent.instance()
child = Child.instance()
print(id(parent)) # 4402124336
print(id(child)) # 4402124336
分析原因: 通过测试,我们发现创建的子类实例和父类实例地址相同是同一个实例,这样导致当子类重写父类某些函数时是不能正常调用。造成该现象的原因不难分析,由于先初始化父类对象,这样会创建一个父类_instance实例,这时候在初始化子类对象,子类没有_instance类变量,继承使用了父类的_instance类变量。由于父类的_instance已经实例化,所以子类会直接使用。
解决方案: 重写如下的单例类,根据当前类名去初始化实例类对象。
class Singleton(object):
@classmethod
def instance(cls):
instance_name = f"{cls.__name__}_instance"
_instance = getattr(cls, instance_name, None)
if not _instance:
_instance = cls()
setattr(cls, instance_name, _instance)
return _instance