Найти - Пользователи
Полная версия: вопросы по паттерну Синглтон(Borg)
Начало » Python для экспертов » вопросы по паттерну Синглтон(Borg)
1
lobster
Всех приветствую!
Сама программа небольшая, но там дважды вызывается конфигурационный класс для извлечения некоторых переменных, я подумал будет лучше сделать этот класс синглтоном, чтобы один раз проинициализировав эти переменные, последующие вызовы не затрагивают эти переменные а просто возвращают эти переменные, ну вобщем нашел одну реализацию этого паттерна - Borg, вот пример:

 class Borg(object):
    __shared_state__ = {}
 
    def __init__(self):
        self.__dict__ = self.__shared_state__
 
class Singletone(Borg):
    def __init__(self, name=None):
        super(Singletone, self).__init__()
        if name:
            self.name = name
 
obj1 = Singletone('Hello, Borg!")
obj2 = Singletone()
print(obj1.name, obj2.name)
 
Вначале вошел в легкий ступор, как это значение переменной self.name оказывается в self.__shared_state__ после инициализации класса родителя, но потом понял что self.__dict__ = self.__shared_state__ это не присваивание, а передача указателя, выходит что при инициализации self.name = name в словарь self.__dict__ автоматом добавляется аттрибут self.name. Непонятно где хранится переменная __shared_state__ в каком объекте? Если к примеру попробовать удалить объект, то ничего не выйдет:

 obj1 = Singletone('Hello, Borg!")
del(obj1)
print(Singletone().name) # out -> Hello, Borg!

4kpt_IV
Вообще не понял при чем здесь синглетон
lobster
4kpt_IV
Вообще не понял при чем здесь синглетон
Ану вобщем то да, лишний класс оказался ни кчему:
 class Borg(object):
    __shared_state__ = {}
 
    def __init__(self, name=None):
        self.__dict__ = Borg.__shared_state__
        if name:
            self.name = name
 
 
obj1 = Borg('Hello')
obj2 = Borg()
 
print(obj1.name, obj2.name)
 

Похоже просветление потихоньку приходит, __shared_state__ - это статический атрибут который можно получить не инициализировав класс
Shaman
https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)#Python
Хотя, создание нескольких объектов того, что должно быть единственным является логической ошибкой, имхо.
PooH
а чем такой вариант плох?
 __all__ = ('config',)
 
class Config():
    pass
 
__config = None
 
def config():
    global __config
    if not __config:
        __config = Config()
    return __config

Или еще проще

 __all__ = ('config',)
 
class Config():
    pass
 
config = Config() 
PooH
lobster
Непонятно где хранится переменная __shared_state__ в каком объекте? Если к примеру попробовать удалить объект, то ничего не выйдет
В классе хранится.
lobster
Shaman
https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)#PythonХотя, создание нескольких объектов того, что должно быть единственным является логической ошибкой, имхо.
Да вообще, использовать синглтон это плохо, примерно также плохо как использовать глобальные переменные в коде.
Вот здесь тоже по теме https://rsdn.ru/forum/design/2615563.flat
PooH
В классе хранится.
Ну, до меня дошло, что класс это тоже объект.
Shaman
lobster
Да вообще, использовать синглтон это плохо, примерно также плохо как использовать глобальные переменные в коде.
lobster
Сама программа небольшая, но там дважды вызывается конфигурационный класс для извлечения некоторых переменных, я подумал будет лучше сделать этот класс синглтоном
https://habrahabr.ru/post/125238/
 kk86 29 июля 2011 в 19:05
+11
Синглтон — зло, когда применён не к месту. Разве нет?
Doggy 29 июля 2011 в 19:09
+9
. . .
TheShock 29 июля 2011 в 21:48
+1
Проблема в том, что простота этого паттерна стала причиной ПОСТОЯННОГО применения Синглтона не к месту.
Хотя, вот лично я, не могу представить, когда он может быть нужен на практике.
В обозначенной ситуации обычно делаю что-то такое
 class Initializer:
 
    def __init__(self):
        self.initialized = False
 
    def init_by_need(self):
        if self.initialized:
            return
        # do initializations
        print('Init complete!')
        self.initialized = True
 
 
initializer = Initializer()
 
if __name__ == '__main__':
    for i in range(10):
        if i in [2, 5]:
            initializer.init_by_need()
Создавать несколько инициализаторов, или проверять их уникальность бессмысленно, поведение класса очевидно.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB