我想阻止继承类的多次实例化。单身模式似乎适合这项任务,但我没有得到我预期的结果。
这是我的代码示例:
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Config(metaclass=Singleton):
def __init__(self):
print('initialized')
class DevelopConfig(Config):
pass
class TestingConfig(Config):
pass
foo = DevelopConfig()
bar = TestingConfig()
执行此操作,我希望看到一个"初始化"作为输出,但它出现两次。关于如何防止这些类的多个实例的任何想法?我错过了什么?
编辑:最终目标是防止多个同时配置。如果有更聪明的方式,我很乐意听到它。
答案 0 :(得分:1)
您遇到的主要问题是cls
实际上并不是您的想法。仅仅因为变量被称为cls
并不意味着它是类对象,在这种情况下它实际上是self
,即创建的对象。
如果您向Singleton类添加print
语句,则可以看到:
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
print(cls)
#etc...
>>> foo = DevelopConfig()
<class '__main__.DevelopConfig'>
initialized
>>> bar = TestingConfig()
<class '__main__.TestingConfig'>
initialized
来自docs
object.__call__(self[, args...])
实例被“调用”时调用 作为一个功能;如果定义了此方法,
x(arg1, arg2, ...)
是一个x.__call__(arg1, arg2, ...)
的简写。
我建议删除字典,如果只想存在一个实例,则不应该使用它。这简化了问题。
class Singleton(type):
_instance = None
def __call__(self, *args, **kwargs):
if not Singleton._instance:
Singleton._instance = super(Singleton, self).__call__(*args, **kwargs)
return Singleton._instance
class Config(metaclass=Singleton):
def __init__(self):
print('initialized')
class DevelopConfig(Config):
pass
class TestingConfig(Config):
pass
这会产生:
>>> foo = DevelopConfig()
initialized
>>> bar = TestingConfig()
>>> foo
<__main__.DevelopConfig object at 0x00000259CE2FD080>
>>> bar
<__main__.DevelopConfig object at 0x00000259CE2FD080>
>>>