Python Borg模式问题

7 投票
7 回答
8561 浏览
提问于 2025-04-15 11:07

我在用Python实现一个borg的时候遇到了问题。我在这个问题的回答中找到了一个例子,但对我来说它不起作用,可能是我漏掉了什么。以下是代码:


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”,但对我来说它只打印了一个空行。你们觉得这可能是什么原因呢?

7 个回答

1

问题似乎是init()这个函数把myvalue的值重置成了一个空字符串。当我把那行代码去掉后,我得到了预期的结果。

4

self.__myvalue = "" 这行去掉,再结合新式的Borg,还有建议在变量名中避免使用 __,我们就得到了:

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

看起来这个功能运行得太好了 :-)

问题在于,在 __init__ 里执行的 self.__myvalue = "" 这行代码,每次创建新的 Borg 对象时都会把 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

撰写回答