Проблема с Python Borg - PullRequest
       15

Проблема с Python Borg

7 голосов
/ 14 апреля 2009

У меня проблемы с внедрением borg в python. Я нашел пример в ответе на этот вопрос , но он не работает для меня, если я что-то упустил. Вот код:


class Config:
    """
    Borg singleton config object
    """
    __we_are_one = {}
    __myvalue = ""

    def __init__(self):
        #implement the borg pattern (we are one)
        self.__dict__ = self.__we_are_one
        self.__myvalue = ""

    def myvalue(self, value=None):
        if value:
           self.__myvalue = value
        return self.__myvalue

conf = Config()
conf.myvalue("Hello")
conf2 = Config()
print conf2.myvalue()

Я предполагаю, что это предназначено для печати "Hello", но для меня это просто печатает пустую строку. Есть идеи, почему это может быть?

Ответы [ 6 ]

13 голосов
/ 14 апреля 2009

Похоже, что это работает слишком хорошо: -)

Проблема заключается в том, что присваивание self.__myvalue = "" в __init__ всегда будет забивать значение myvalue каждый раз, когда создается новый Борг. Вы можете увидеть это, если добавите в тест некоторые дополнительные операторы печати:

conf = Config()
conf.myvalue("Hello")
print conf.myvalue()  # prints Hello
conf2 = Config()
print conf.myvalue()  # prints nothing
print conf2.myvalue() # prints nothing

Удалите self.__myvalue и все будет хорошо.

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

class Config(object):
    """
    Borg singleton config object
    """
    _we_are_one = {}

    def __init__(self):
        #implement the borg pattern (we are one)
        self.__dict__ = self._we_are_one

    def set_myvalue(self, val):
        self._myvalue = val

    def get_myvalue(self):
        return getattr(self, '_myvalue', None)

    myvalue = property(get_myvalue, set_myvalue)

c = Config()
print c.myvalue # prints None
c.myvalue = 5
print c.myvalue # prints 5
c2 = Config()
print c2.myvalue #prints 5
4 голосов
/ 14 апреля 2009

Объединяя удаление self.__myvalue = "" с новым стилем Борг и предложениями избегать __ в именах переменных, мы получаем:

class Config(object):
    """
    Borg singleton config object
    """
    _we_are_one = {}
    _myvalue = ""

    def __new__(cls, *p, **k):
        self = object.__new__(cls, *p, **k)
        self.__dict__ = cls._we_are_one
        return self

    def myvalue(self, value=None):
        if value:
           self._myvalue = value
        return self._myvalue

if __name__ == '__main__':
    conf = Config()
    conf.myvalue("Hello")
    conf2 = Config()
    print conf2.myvalue()
1 голос
/ 01 февраля 2011
class Borg(object):
    """Demonstrating the Borg-pattern: All the instances of a class already
    know what one of them learned... Scary, isn't it?"""

    def __init__(self, name):
        self.name = name

    @classmethod
    def borg_knowledge(cls, who_is_it):
        if hasattr(cls, "b_knowledge"):
            return "%s: I already know that the borg pattern is awesome!" % who_is_it
        else:
            cls.b_knowledge = True
            return "%s: Learning about the borg pattern..." % who_is_it

    def personal_experience(self):
        if hasattr(self, "p_knowledge"):
            return "%s: I already know that!" % self.name
        else:
            self.p_knowledge = True
            return "%s: Learning something..." % self.name


b1 = Borg("b1")
b2 = Borg("b2")
print ">> Created b1 and b2, both Borg"; print

print ">> Usual class behavior. One instance does not know what the other does."
print b1.personal_experience()
print b2.personal_experience()

print
print ">> Borg have a shared knowledge a.k.a. why classmethods are different!"
print b1.borg_knowledge(b1.name)
print b2.borg_knowledge(b2.name)
1 голос
/ 14 апреля 2009

Проблема заключается в том, что init () сбрасывает myvalue в пустую строку. Когда я удаляю эту строку, я получаю ожидаемый результат.

0 голосов
/ 04 декабря 2014

Я пытался реализовать это, используя «старый стиль», а также «новый стиль», и я не вижу разницы между ними. Есть ли преимущество одного над другим? Или они в основном эквивалентны?

class Borg(object):
    shared_state = {'a_value': True}
    def __init__(self):
        self.__dict__ = self.shared_state


class NewBorg(object):
    shared_state = {'a_value': True}

    def __new__(cls, *p, **k):
        self = object.__new__(cls, *p, **k)
        self.__dict__ = cls.shared_state
        return self


borg_a = Borg()
borg_b = Borg()

print id(borg_a), '!=', id(borg_b)
assert borg_a.shared_state == borg_b.shared_state
borg_a.shared_state['a_value'] = False
assert borg_a.shared_state == borg_b.shared_state

new_borg_a = NewBorg()
new_borg_b = NewBorg()

print id(new_borg_a), '!=', id(new_borg_b)
assert new_borg_a.shared_state == new_borg_b.shared_state
new_borg_a.shared_state['a_value'] = False
assert new_borg_a.shared_state == new_borg_b.shared_state
0 голосов
/ 09 апреля 2011
> The problem appears to be that init() is resetting myvalue to an
> empty string. When You remove that
> line ('self.__myvalue = ""')  then you will get the expected
> output.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...