views:

1054

answers:

3

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?

+2  A: 

The problem appears to be that init() is resetting myvalue to an empty string. When I remove that line I get the expected output.

Dave Costa
+7  A: 

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 implementationg of myvalue() is a little weird. Better, I'd say, to have explicit setters 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
Jarret Hardie
Ha! Fairly obvious really, should have spotted it. Thanks for the tips all.
+2  A: 

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