为什么这个Python Borg / Singleton模式有效

Why is this Python Borg / Singleton pattern working

我只是在网上绊了一跤,发现这些有趣的代码被剪掉了:

http://code.activestate.com/recipes/66531/

1
2
3
4
5
class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

我理解单件是什么,但我不理解被截取的特定代码。你能给我解释一下,"共享"状态是如何/在哪里被改变的吗?

我在ipython尝试过:

1
2
3
4
5
6
7
8
9
10
11
12
In [1]: class Borg:
   ...:         __shared_state = {}
   ...:     def __init__(self):
   ...:             self.__dict__ = self.__shared_state
   ...:     # and whatever else you want in your class -- that's all!
   ...:
In [2]: b1 = Borg()
In [3]: b2 = Borg()
In [4]: b1.foo="123"
In [5]: b2.foo
Out[5]: '123'
In [6]:

但不能完全理解这是如何发生的。


因为class's实例的__dict__设置为等于__share_statedict。它们指向同一对象。(Classname.__dict__包含所有类属性)

当你这样做的时候:

1
b1.foo ="123"

您正在修改b1.__dict__Borg.__shared_state所指的dict


实例是单独的对象,但是通过将它们的__dict__属性设置为相同的值,这些实例具有相同的属性字典。python使用属性字典来存储对象上的所有属性,因此实际上,两个实例的行为方式相同,因为对它们的属性的每次更改都是对共享属性字典进行的。

但是,如果使用is来测试平等(浅平等),对象仍然会比较不平等,因为它们仍然是不同的实例(很像单独的博格无人驾驶飞机,它们共享自己的想法,但在物理上是不同的)。


在实例化任何对象后调用的__init__方法将新创建对象的__dict__属性替换为类属性__shared_state

a.__dict__b.__dict__Borg._Borg__shared_state都是同一个对象。注意,在从类外部访问私有属性时,我们必须添加隐式前缀_Borg

1
2
In [89]: a.__dict__ is b.__dict__ is Borg._Borg__shared_state
Out[89]: True