为什么基类单例仍会多次调用构造函数?

时间:2019-01-21 10:07:50

标签: python singleton

我正在定义如下的Python单例:

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__()方法 still 。例如,

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

答案 0 :(得分:1)

创建实例包括两个步骤:①通过调用cls.__new__()创建一个“空白”实例,然后②通过调用obj.__init__()初始化此空白实例。

在您的情况下,创建类的新实例将调用您的__new__(),该实例总是返回相同(不是很空白)的实例,然后通过在其中调用__init__()对其进行正确初始化(抱歉pun)。

我不确定是否有办法避免调用__init__(),至少没有简单的方法。我会接受这一点,只是保留一个空的__init__(),它在被调用时不会受到伤害。

或者,也许通常最好不要创建单例的新实例(由于特殊的__new__()方法,因此恰好是 same 实例) 。相反,只需使用cls.singleton来存储您唯一的一个实例(单例),或者仅使用类本身作为单例并在类和静态方法中进行所有操作。我通常会选择后者。