在两个不同模块中使用Borg模式时出现意外行为

1 投票
5 回答
519 浏览
提问于 2025-04-15 14:14

我在使用Borg模式,并且模块之间互相包含。下面是一个示例代码(虽然不是实际代码,但能展示问题)。在这个例子中,我有两个不同的Borg,因为类名(我想类本身)在解释器看来是不同的。

有没有办法在这种情况下使用Borg,而不需要重新设计模块架构呢?

模块 borg.py

import borg2

class Borg:
    _we_are_one = {}

    def __init__(self):
        self.__dict__ = Borg._we_are_one
        try:
            self.name
        except AttributeError:
            self.name = "?"
        print self.__class__, id(self.__dict__)

def fct_ab():
    a = Borg()
    a.name = "Bjorn"

    b = Borg()
    print b.name

if __name__ == "__main__":
    fct_ab()
    borg2.fct_c()

模块 borg2.py

import borg

def fct_c():
    c = borg.Borg()
    print c.name

结果是

__main__.Borg 40106720
__main__.Borg 40106720
Bjorn
borg.Borg 40106288
?

为了更清楚地说明我的问题:为什么Python会把 __main__.Borgborg.Borg 视为两个不同的类呢?

5 个回答

1

问题不在于类的名字。我不太明白为什么Python会把Borg类和borg.Borg类看作不同的东西,可能是因为你是从__main__运行的,我觉得Python没有意识到__main__和borg其实是同一个模块。

解决这个问题很简单。把fct_ab改成:

def fct_ab():
    import borg
    a =  borg.Borg()
    a.name = "Bjorn"

    b = borg.Borg()
    print b.name

这样就能解决问题了。

4

经过一天和单例模式以及博格模式的斗争,我得出了以下结论:

看起来,如果一个Python模块通过不同的“导入路径”被多次导入,那么这个模块实际上是被导入了多次。如果这个模块里面有单例对象,你就会得到多个实例。

举个例子:

myproject/
  module_A
  some_folder/
    module_B
    module_C

如果module_A通过 from myproject.some_folder import module_C 导入了module_C,而module_B则通过 import module_C 导入了同一个module_C,那么这个模块实际上被导入了两次(至少根据我的观察是这样的)。通常情况下,这没什么大不了的,但对于单例或博格模式来说,你实际上得到了两个本该是唯一的实例。(这就意味着有两组博格,它们各自有不同的内部状态)。

解决办法是:给自己定一个导入模块的规则,并坚持下去。我会从一个共同的根文件夹开始导入所有模块,即使模块文件和我正在工作的文件是平行的。在上面的例子中,module_A和module_B都通过 from myproject.some_folder import module_C 来导入module_C。

3

这个问题只出现在你的主函数里。把那段代码移到一个单独的文件中,其他的就会像你预期的那样运行。这个代码

import borg
import borg2

if __name__ == "__main__":
    borg.fct_ab()
    borg2.fct_c()

会产生这个输出:

borg.Borg 10438672
borg.Borg 10438672
Bjorn
borg.Borg 10438672
Bjorn

撰写回答