<p>在第一个示例中,没有将<code>+=</code>运算符应用于字典。您将它应用于存储在<code>d['a']</code>键中的值,这是一个完全不同的对象。</p>
<p>换句话说,Python将检索<code>d['m']</code>(一个<code>__getitem__</code>调用),对其应用<code>+=</code>运算符,然后将该表达式的结果设置回<code>d['m']</code>(一个<code>__setitem__</code>调用)。</p>
<p><code>__iadd__</code>方法要么返回经过适当修改的<code>self</code>,要么返回一个新对象,但Python无法确定返回的是什么。所以它总是要调用<code>d.__setitem__('m', <return_value_from_d['m'].__iadd__(1)>)</code>。</p>
<p>如果你这样做了,同样的事情也会发生:</p>
<pre><code>m = d['m']
m += 1
d['m'] = m
</code></pre>
<p>但是在全局命名空间中没有额外的名称<code>m</code>。</p>
<p>如果<code>mutable()</code>实例没有存储在字典中,而是存储在全局命名空间中,则会发生完全相同的事件序列,但直接存储在<code>globals()</code>字典中,您将看不到<code>__getitem__</code>和<code>__setitem__</code>调用。</p>
<p>这是在<a href="http://docs.python.org/2/reference/simple_stmts.html#augmented-assignment-statements" rel="noreferrer">augmented assignment reference documentation</a>下记录的:</p>
<blockquote>
<p>An augmented assignment evaluates the target (which, unlike normal assignment statements, cannot be an unpacking) and the expression list, performs the binary operation specific to the type of assignment on the two operands, and assigns the result to the original target.</p>
</blockquote>
<p>其中<code>d['m']</code>是目标;在这里对目标求值涉及<code>__getitem__</code>,将结果分配回原始目标调用<code>__setitem__</code>。</p>