Python borg pattern problem


Question

I'm having problems implementing a borg in python. I found an example in an answer to this question but it's not working for me, unless I'm missing something. Here's the code:


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()

I assume this is meant to print "Hello", but for me it just prints a blank line. Any ideas why this might be?

1
7
5/23/2017 12:19:32 PM

Accepted Answer

It looks like it's working rather too well :-)

The issue is that the assignment self.__myvalue = "" in __init__ will always clobber the value of myvalue every time a new Borg is, er, created. You can see this if you add some additional print statements to your test:

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

Remove the self.__myvalue and things will be fine.

Having said that, the implementation of myvalue() is a little weird. Better, I'd say, to have explicit getters and setters using properties. You'll also want some code in __init__ to initialize the value of myvalue if it doesn't exist yet, or to at least handle that it might not exist in the getter. Perhaps something like:

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
13
12/13/2012 12:12:41 AM

Combining the removal of self.__myvalue = "" with the new-style Borg and the suggestions to avoid __ in variable names, we get:

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()

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon