<p>在此代码中:</p>
<pre><code>class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
</code></pre>
<ul>
<li><code>__shared_state = {}</code>行出现在类级别,因此它只添加一次到类<code>Borg</code>,而不是添加到类型为<code>Borg</code>的每个单独对象。这与之后写<code>Borg.__shared_state = {}</code>是一样的</李>
<li><code>self.__dict__ = self.__shared_state</code>令人困惑,因为它使用了<code>self.</code>两次,但效果非常不同:
<ul>
<li>当<strong>赋值给</strong><code>self.something</code>时,在对象<code>self</code>中设置该<code>something</code>。这并不奇怪</李>
<li>但是当<strong>从</strong><code>self.something</code>读取时,首先在<code>self</code>对象中查找<code>something</code>,如果在那里找不到,则在对象的类中查找。这种想法听起来很奇怪,但实际上你一直在使用它:这就是方法通常的工作方式。例如,在<code>s = "foo"; b = s.startswith("f")</code>中,对象<code>s</code>没有属性<code>startswith</code>,但是它的类<code>str</code>有属性,这就是调用该方法时使用的</李>
</ul></li>
</ul>
<p>这一行:</p>
<pre><code>b1.val1 = 'Jaga Gola!!!'
</code></pre>
<p>最终转化为:</p>
<pre><code>b1.__dict__['val1'] = 'Jaga Gola!!!'
</code></pre>
<p>但是我们知道<code>b1.__dict__</code>等于<code>Borg.__shared_state</code>,所以它被分配给它。然后:</p>
<pre><code>print(b2.val1, ...
</code></pre>
<p>翻译为:</p>
<pre><code>print(b2.__dict__['val1'])
</code></pre>
<p>我们再次知道<code>b2.__dict__</code>等于相同的</strong>{<cd18>},因此<code>val1</code>被发现</p>
<p>如果您在开始时删除了关于<code>__shared_state</code>的内容,那么<code>b1</code>和<code>b2</code>将获得它们自己的<code>__dict__</code>对象,因此将<code>val1</code>放入<code>b1</code>的dict中对<code>b2</code>没有影响,这就是您所提到的错误的原因</p>
<hr/>
<p>这对于理解正在发生的事情来说是很好的,但是您应该意识到这段代码并不能保证工作,并且可能会在Python的未来版本或其他实现(如PyPy)中崩溃。<a href="https://docs.python.org/3/library/stdtypes.html#special-attributes" rel="nofollow noreferrer">Python documentation for ^{<cd25>}</a>将其描述为“只读属性”,因此根本不应该为其赋值。不要在其他人可能运行的代码中执行此操作</p>
<p>事实上,认为<code>a.foo</code>就是<code>a.__dict__['foo']</code>的想法是一个巨大的简化。首先,我们已经遇到了这样的情况:有时在阅读时,它后面跟着<code>a.__class__.__dict__['foo']</code>。另一个例子是<code>a.__dict__</code>显然不是<code>a.__dict__['__dict__']</code>,否则它将如何结束!?这个过程有些复杂,在<a href="https://docs.python.org/3/reference/datamodel.html#customizing-attribute-access" rel="nofollow noreferrer">the Data Model docs</a>中有记录</p>
<p>获得此行为的支持方式是使用特殊的<code>__setattr__</code>和<code>__getattr__</code>方法(也在这些数据模型文档中描述),如下所示:</p>
<pre><code>class Borg:
__shared_state = {}
def __getattr__(self, name):
try:
return Borg.__shared_state[name]
except KeyError:
raise AttributeError
def __setattr__(self, name, value):
Borg.__shared_state[name] = value
</code></pre>