Как манипулировать синглтоном? - PullRequest
0 голосов
/ 19 июня 2019

Для определения Singleton в Python (например), мы можем определить его как

class Singleton(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super().__init__(*args, **kwargs)
    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super().__call__(*args, **kwargs)
            return self.__instance
        else:
            return self.__instance

class A(object, metaclass=Singleton):
    //code

Мой вопрос: если мы создадим два экземпляра класса A, метод Singleton __init__ не получитзвонил дважды?Как удается вызвать метод __call__ вместо __init__?

1 Ответ

1 голос
/ 20 июня 2019

Вы превысили __call__, поэтому A.__new__ не вызывается, если self.__instance не None.Нет вызова A.__new__, нет неявного вызова A.__init__.

Метакласс __init__ метод не становится __init__ методом A;он вызывается, когда выполняется оператор class.Таким образом, в этом случае, после того, как

class A(metaclass=Singleton):
    pass

A.__instance будет существовать, инициализируется None Singleton.__init__.

Учитывая ваше определение A, A() оценивается какSingleton.__call__(A), с A привязанным к self.Если A.__instance по-прежнему None, то вызывается type.__call__(A), который вызывает A.__new__, создавая новый экземпляр.


Использование модуля, который juanpa.arrivillaga и я намекаем назаменяет класс типа

class A(metaclass=Singleton):
    x = 3
    def __init__(self, y):
        self.y = 9

    def combine(self):
        return self.x + self.y

на модуль A.py, который выглядит как

x = 3

def init(val):
    global y
    y = val

def combine():
    return x + y

Переменные и методы экземпляра становятся функциями верхнего уровня и глобальными переменными модуля.Нет реальной разницы между атрибутом класса и атрибутом экземпляра, если существует только один экземпляр.A.init должен быть вызван напрямую.Если он не принимает никаких аргументов, вы можете опустить его и поместить код на верхний уровень, где он вызывается при импорте.(Не существует параметризованной формы импорта, в которой import A(3) импортировал бы A.py и передал бы 3 в качестве аргумента в код верхнего уровня.)

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