<p>不能在创建类之后动态更改<code>__slots__</code>属性。这是因为该值用于为每个插槽创建特殊的<a href="https://docs.python.org/3/reference/datamodel.html#descriptors" rel="noreferrer"><em>descriptors</em></a>。从<a href="https://docs.python.org/3/reference/datamodel.html#notes-on-using-slots" rel="noreferrer">^{<cd1>} documentation</a>开始:</p>
<blockquote>
<p><code>__slots__</code> are implemented at the class level by creating descriptors (<em>Implementing Descriptors</em>) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by <code>__slots__</code>; otherwise, the class attribute would overwrite the descriptor assignment.</p>
</blockquote>
<p>您可以在类<code>__dict__</code>中看到描述符:</p>
<pre><code>>>> class A:
... __slots__ = ['x']
...
>>> A.__dict__
mappingproxy({'__module__': '__main__', '__doc__': None, 'x': <member 'x' of 'A' objects>, '__slots__': ['x']})
>>> A.__dict__['x']
<member 'x' of 'A' objects>
>>> a = A()
>>> A.__dict__['x'].__get__(a, A)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: x
>>> A.__dict__['x'].__set__(a, 'foobar')
>>> A.__dict__['x'].__get__(a, A)
'foobar'
>>> a.x
'foobar'
</code></pre>
<p>您不能自己创建这些附加描述符。即使可以,也不能为该类生成的实例上的额外插槽引用分配更多的内存空间,因为这是存储在该类的C结构中的信息,而不是以Python代码可以访问的方式</p>
<p>这一切都是因为<code>__slots__</code>只是Python代码中组成Python实例的元素的低级处理的扩展;<em>常规</em>Python实例上的<code>__dict__</code>和<code>__weakref__</code>属性始终作为插槽实现:</p>
<pre><code>>>> class Regular: pass
...
>>> Regular.__dict__['__dict__']
<attribute '__dict__' of 'Regular' objects>
>>> Regular.__dict__['__weakref__']
<attribute '__weakref__' of 'Regular' objects>
>>> r = Regular()
>>> Regular.__dict__['__dict__'].__get__(r, Regular) is r.__dict__
True
</code></pre>
<p>Python开发人员在这里所做的全部工作就是扩展系统,使用任意名称添加更多此类插槽,这些名称取自所创建类的<code>__slots__</code>属性,以便<em>节省内存</em>;字典比插槽中的值的简单引用占用更多内存。通过指定<code>__slots__</code>,可以禁用<code>__dict__</code>和<code>__weakref__</code>插槽,除非在<code>__slots__</code>序列中显式包含这些插槽</p>
<p>扩展槽的唯一方法是子类;您可以使用<code>type()</code>函数或使用工厂函数动态创建子类:</p>
<pre><code>def extra_slots_subclass(base, *slots):
class ExtraSlots(base):
__slots__ = slots
ExtraSlots.__name__ = base.__name__
return ExtraSlots
</code></pre>