代码之家  ›  专栏  ›  技术社区  ›  Dmitri Nesteruk

为什么基类singleton仍然多次调用构造函数?

  •  0
  • Dmitri Nesteruk  · 技术社区  · 6 年前

    我将定义一个python singleton,如下所示:

    class Database:
        initialized = False
    
        def __init__(self):
            self.id = random.randint(1,101)
            print("Generated an id of ", self.id)
            print("Loading database from file")
    
        _instance = None
    
        def __new__(cls, *args, **kwargs):
            if not cls._instance:
                cls._instance = super(Database, cls)\
                    .__new__(cls, *args, **kwargs)
            return cls._instance
    

    这就意味着每一个电话 Database() 实际上只返回一个实例。然而, __init__() 方法是 仍然 每次调用时调用。例如,

    database = Database()
    
    if __name__ == '__main__':
        d1 = Database()
        d2 = Database()
    
        print(d1.id, d2.id)
        print(d1 == d2)
        print(database == d1)
    

    产生输出

    Generated an id of  8
    Loading database from file
    Generated an id of  89
    Loading database from file
    Generated an id of  81
    Loading database from file
    81 81
    True
    True
    

    为什么会这样?我该怎么做才能避免初始化器被多次调用?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Alfe    6 年前

    创建实例有两个步骤:通过调用 cls.__new__() ,然后通过调用 obj.__init__() .

    在您的例子中,创建类的新实例会调用 __new__() 它总是返回相同的(不是空的)实例,然后通过调用 __init__() 在里面(为双关语道歉)。

    我不确定是否有办法避免打电话给 γ-iITI^() 我想,至少没有直行的。我会接受这个,只留下一个空的 γ-iITI^() 打电话时不会疼。

    或者,也许一般来说,最好不要创建新的单例实例(结果恰好是 相同的 因为你的特殊 α-NexSuh() 方法)。只需使用 cls.singleton 要存储一个且唯一的实例(singleton),或者只使用类本身作为singleton,并使所有内容都在类和静态方法中。我通常选择后者。