通过定义特殊变量__slot__, 类可以限制对合法实例属性名称的设置,如下所示:
class Account(object):
__slots__ = ('name', 'balance')
...
定义__slots__后,可以在实例上分配的属性名称将被限制为指定的名称。否则将引发AttributeError异常。这种限制可以阻止其他人向现有实例添加新属性,解决了用户将值分配给他们无法正确拼写的属性时出现的问题。
在实际使用中, __slots__从未被当做一种安全的特性来实现。它实际上是对内存和执行速度的一种性能优化。使用__slots__的类的实例不再使用字典来存储实例数据。相反,会使用基于数组的更加紧凑的数据结构。在会创建大量对象的程序中,使用__slots__可以显著减少内存占用和执行时间。
注意, __slots__与继承的配合使用需要一定的技巧。如果类继承自使用__slots__的基类,那么它也需要定义__slots__来存储自己的属性(即使它不会添加任何属性也是如此),这样才能充分利用__slots__提供的优势。如果忘记这一点,派生类的运行速度将会更慢,占用的内存也比未在任何类上使用__slots__时多。
__slots__的使用也可以使代码不必要求实例具有底层__dict__属性。尽管这一点通常不适用于用户代码,但可以编写其他支持对象实用工具库和其他工具,依靠__dict__来调试、序列化对象并执行其他操作。
最后,__slots__的存在不会对__getattribute__(), __getattr__(), __setattr__()等方法的调用产生任何影响,因为这些方法应该在类中重新定义。但是,这些方法的默认行为将考虑到__slots__。此外应该强调一点,没有必要向__slots__添加方法或特性名称,因为它们存储在类中,而不是存储在每个实例中。