<p>为了支持任意属性分配,一个对象需要一个<code>__dict__</code>:一个与该对象相关联的dict,其中可以存储任意属性。否则,就没有地方可以放入新的属性。</p>
<p>一个<code>object</code>的实例不会携带一个<code>__dict__</code>——如果它携带了,在可怕的循环依赖问题之前(因为<code>dict</code>,和大多数其他东西一样,继承自<code>object</code>;-),这将为Python中的每个</em>对象都添加一个dict,这意味着每个当前没有或需要dict的对象都有<em>个</em>字节的开销(本质上,没有任意可分配属性的所有对象都没有或需要dict)。</p>
<p>例如,使用优秀的<code>pympler</code>项目(您可以从<a href="http://code.google.com/p/pympler/source/checkout" rel="noreferrer">here</a>通过svn获得它),我们可以进行一些测量…:</p>
<pre><code>>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
</code></pre>
<p>你不会希望每个<code>int</code>占用144字节而不是16字节,对吧?-)</p>
<p>现在,当你创建一个类(继承自任何类)时,事情会发生变化…:</p>
<pre><code>>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
</code></pre>
<p>…现在添加了<code>__dict__</code><em>(加上一点开销),因此<code>dint</code>实例可以具有任意属性,但是您为这种灵活性付出了相当大的空间代价。</p>
<p>那么,如果您想要<code>int</code>s只使用一个<em>one</em>额外属性<code>foobar</code>。。。?这是一种罕见的需求,但Python确实为此提供了一种特殊的机制。。。</p>
<pre><code>>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
</code></pre>
<p>……不是像<code>int</code>那么小,小心!(甚至是两个<code>int</code>,一个是<code>self</code>,另一个是<code>self.foobar</code>——第二个可以重新分配),但肯定比一个<code>dint</code>要好得多。</p>
<p>当类具有<code>__slots__</code>特殊属性(字符串序列)时,那么<code>class</code>语句(更准确地说,默认元类<code>type</code>)并没有为该类的每个实例配备<code>__dict__</code>(因此也就具备了拥有任意属性的能力),只是一组有限的、严格的“槽”(基本上是放置每一个都可以包含一个对某个对象的引用)和给定的名称。</p>
<p>作为失去灵活性的交换,每个实例获得了大量字节(可能只有当您有无数个实例到处闲逛时才有意义,但是<em>是</em>的用例)。</p>