防止初始化扩展单例类

时间:2017-05-19 12:25:11

标签: python inheritance singleton

我想阻止继承类的多次实例化。单身模式似乎适合这项任务,但我没有得到我预期的结果。

这是我的代码示例:

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()

执行此操作,我希望看到一个"初始化"作为输出,但它出现两次。关于如何防止这些类的多个实例的任何想法?我错过了什么?

编辑:最终目标是防止多个同时配置。如果有更聪明的方式,我很乐意听到它。

1 个答案:

答案 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>
>>>