Почему синглтон базового класса все еще вызывает конструктор несколько раз? - PullRequest
0 голосов
/ 21 января 2019

Я определяю синглтон 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__() это все еще , вызываемый при каждом вызове. Например,

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 голосов
/ 21 января 2019

Создание экземпляра выполняется в два этапа: ① Создайте «пустой» экземпляр, вызвав cls.__new__(), затем ② инициализируйте этот пустой экземпляр, вызвав obj.__init__().

В вашем случае создание нового экземпляра вашего класса вызывает ваш __new__(), который всегда возвращает один и тот же (не очень пустой) экземпляр, который затем инициализируется должным образом, вызывая в нем __init__() (извините за каламбур).

Я не уверен, есть ли способ избежать вызова __init__(), по крайней мере, не прямой, я думаю. Я принял бы это и просто оставил бы пустой __init__(), который не повредит при вызове.

Или, может быть, лучше вообще не создавать новые экземпляры вашего синглтона (которые затем оказываются таким же экземпляром благодаря вашему специальному __new__() методу). Вместо этого просто используйте cls.singleton для хранения вашего единственного экземпляра (синглтона) или просто используйте сам класс как синглтон и сделайте все в классе и статических методах. Обычно я выбираю второй вариант.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...