我想防止继承类的多个实例化。单例模式似乎适合这项任务,但我没有完全得到我预期的结果。
这是我的代码示例:
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()
执行此操作时,我希望看到一个“初始化”作为输出,但它出现了两次。关于如何防止这些类的多个实例有什么想法吗?我错过了什么?
编辑:最终目标是防止多个并发配置。如果有更聪明的方法,我很想听听。
最佳答案
您所遇到的问题背后的主要问题是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...])
Called when the instance is “called” as a function; if this method is defined,
x(arg1, arg2, ...)
is a shorthand forx.__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>
>>>
关于python - 防止初始化扩展单例类的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44070080/